我可以(而且我应该)断言组件使用 Enzyme 的 shallow() 呈现哪些 HTML 元素吗?
Can I, (and should I), make assertions about what HTML elements a component renders using Enzyme's shallow()?
问题:
我正在为名为 <BaseEdit />
的 React 组件编写单元测试。为了测试该组件是否有效,我想断言它将呈现一个 HTML 元素 <input/>
,并且我想使用 shallow() 而不是 mount() 来实现。
以下测试用例有效:
const baseEditWrapper = mount(<BaseEdit />)
const inputElement = baseEditWrapper.find('input')
assert(inputElement.exists())
assert.strictEqual(inputElement.prop('type'), 'text')
但是,如果我将 mount()
更改为 shallow()
,则测试失败。它失败了,因为 baseEditWrapper.find('input')
returns 一个 empty/stub/nonexistant ShallowWrapper 对象。
底层HTML:
<BaseEdit />
组件在使用 Enzyme 和 JSDom 安装时会创建以下 DOM 个元素。
<div class="MuiFormControl-root MuiTextField-root WithStyles(ForwardRef(TextField))-root-27 WithStyles(ForwardRef(TextField))-root-96" style="width:120px">
<div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl">
<input type="text" aria-invalid="false" class="MuiInputBase-input MuiInput-input"/>
</div>
</div>
额外详情:
shallow() 的文档是 here。
问题 表明使用 shallow() 时支持通过选择器查找。
下面的测试用例证明 shallow 确实渲染了多层 HTML 元素,并作为我的问题的解决方案。
const shallowWrapper = shallow(<BaseEdit />)
assert(shallowWrapper.html().includes('<input')
assert(shallowWrapper.html().includes('type=\"text\"'))
但是,这样的解决方案似乎很老套,我宁愿让我的解决方案与 Enzyme 的 ShallowWrapper
界面的使用保持一致。
您应该可以使用 .dive()
找到输入:
const input = wrapper.find(TextField).dive().find('input')
如果 input
嵌套在多个 React 组件中,您甚至可能需要多次潜水:
// This is a little contrived, but something like this:
const InnerTextField = () => <input />;
const TextField = () => <InnerTextField />;
const BaseEdit = () => <TextField />;
// You would need to do this to find the input:
const input = wrapper.find(TextField).dive().dive().find('input');
你还问过你是否应该使用shallow
:
如果你想对基础 HTML 进行断言(例如,你想确保 BaseEdit
总是呈现 input
),你最好使用mount
,除非有理由不这样做。
shallow
当您想测试组件树的单层时很有用。看起来您正在使用 Material UI,因此可能的测试可能是检查 BaseEdit
是否将道具正确传递给 TextField
。
it('passes the required prop to the underlying component', () => {
const wrapper = shallow(<BaseEdit required />);
expect(wrapper.find(TextEdit).props().required).toBe(true);
wrapper.setProps({ required: false });
expect(wrapper.find(TextEdit).props().required).toBe(false);
})
问题:
我正在为名为 <BaseEdit />
的 React 组件编写单元测试。为了测试该组件是否有效,我想断言它将呈现一个 HTML 元素 <input/>
,并且我想使用 shallow() 而不是 mount() 来实现。
以下测试用例有效:
const baseEditWrapper = mount(<BaseEdit />)
const inputElement = baseEditWrapper.find('input')
assert(inputElement.exists())
assert.strictEqual(inputElement.prop('type'), 'text')
但是,如果我将 mount()
更改为 shallow()
,则测试失败。它失败了,因为 baseEditWrapper.find('input')
returns 一个 empty/stub/nonexistant ShallowWrapper 对象。
底层HTML:
<BaseEdit />
组件在使用 Enzyme 和 JSDom 安装时会创建以下 DOM 个元素。
<div class="MuiFormControl-root MuiTextField-root WithStyles(ForwardRef(TextField))-root-27 WithStyles(ForwardRef(TextField))-root-96" style="width:120px">
<div class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl">
<input type="text" aria-invalid="false" class="MuiInputBase-input MuiInput-input"/>
</div>
</div>
额外详情:
shallow() 的文档是 here。
问题
下面的测试用例证明 shallow 确实渲染了多层 HTML 元素,并作为我的问题的解决方案。
const shallowWrapper = shallow(<BaseEdit />)
assert(shallowWrapper.html().includes('<input')
assert(shallowWrapper.html().includes('type=\"text\"'))
但是,这样的解决方案似乎很老套,我宁愿让我的解决方案与 Enzyme 的 ShallowWrapper
界面的使用保持一致。
您应该可以使用 .dive()
找到输入:
const input = wrapper.find(TextField).dive().find('input')
如果 input
嵌套在多个 React 组件中,您甚至可能需要多次潜水:
// This is a little contrived, but something like this:
const InnerTextField = () => <input />;
const TextField = () => <InnerTextField />;
const BaseEdit = () => <TextField />;
// You would need to do this to find the input:
const input = wrapper.find(TextField).dive().dive().find('input');
你还问过你是否应该使用shallow
:
如果你想对基础 HTML 进行断言(例如,你想确保 BaseEdit
总是呈现 input
),你最好使用mount
,除非有理由不这样做。
shallow
当您想测试组件树的单层时很有用。看起来您正在使用 Material UI,因此可能的测试可能是检查 BaseEdit
是否将道具正确传递给 TextField
。
it('passes the required prop to the underlying component', () => {
const wrapper = shallow(<BaseEdit required />);
expect(wrapper.find(TextEdit).props().required).toBe(true);
wrapper.setProps({ required: false });
expect(wrapper.find(TextEdit).props().required).toBe(false);
})