酶不模拟 React Material-UI v1 - Select 组件上的更改事件
enzyme not simulating change event on React Material-UI v1 - Select component
所以我开始使用 Jest 和 Enzyme 设置对由 Material-UI 组件组成的 React 组件进行单元测试。到目前为止,每个事件模拟都运行良好,直到我遇到来自 Material-UI 的 Select 组件。 (下面有更多信息)
项目使用 create-react-app 启动并利用 material-ui-next.
依赖版本
- 反应:16.2.0
- 反应-Dom:16.2.0
- 反应脚本:1.1.1
- Material UI: 1.0.0-beta.35
- Jest:随附安装包 (22.4.3)
- 酶:3.3.0
- 酶适配器 React 16:1.1.1
问题
我有一个名为 FiltersDesktop 的纯功能组件,由 Material-UI 表单字段组成。其中三个是 Select 组件,其他是来自 material-ui.
的文本字段和日期选择器
UI代码
<Collapse in={props.visible} className={'filters-container-desk'}>
<Grid container classes={{ typeContainer: "filter-container" }} id={'container-desk'}>
<Grid item lg={2} xl={2}>
<FormControl fullWidth={true}>
<InputLabel htmlFor="sources">Sources</InputLabel>
<Select
open
inputProps={{ name: 'sources-desk', id: 'sources-desk' }}
value={props.filters.source || ''}
onChange={(event) => props.updateFilter({ source: event.target.value })}
>
<MenuItem value=''>
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item lg={2} xl={2}>
...
</Grid>
... // More Grid components of similar structure as above
</Grid>
</Collapse>
当我尝试在文本字段组件上模拟更改事件时,它工作正常。以下是我为测试文本字段而编写的代码:
TextField 的测试代码
const props = {
updateFilter: jest.fn()
};
test(`updateFilter should get called on simulating text changes in domain`, () => {
const component = mount(<FiltersDesktop {...this.props} />);
component.find('#domain-desk').last().simulate('change', { target: { value: 'scoopwhoop.com' } });
expect(props.updateFilter).toHaveBeenCalled();
});
但类似的东西不适用于 Select 组件。但是,当我通过界面实际与 Select 字段交互时,会调用更新函数。以下是我为了测试Select:
而写的测试代码
Select
的测试代码
const props = {
updateFilter: jest.fn()
};
test(`updateFilter should get called on simulating text changes in sources`, () => {
const component = mount(<FiltersDesktop {...this.props} />);
// Did not work
component.find('#sources-desk').last().simulate('change', { target: { value: 20 } });
// Did not work
component.find('Select').first().simulate('change', { taget: { value: 20 } });
// Did not work
component.find('#sources-desk').forEach(element => element.simulate('change', { taget: { value: 20 } }))
expect(props.updateFilter).toHaveBeenCalled();
});
由于某些原因,在上述所有情况下,find 方法总是返回超过 1 个元素,因此我在适当的情况下使用 first、last 和 forEach。
请帮助我找出在模拟 Select 组件时未触发更改事件的原因。
请放心,我至少花了一周时间阅读 Github 上的问题,尝试实施解决方案并测试 Jest 和 Enzyme 的 guides。我确信我的测试设置很好,因为其余情况都运行良好。
如果您想准确查看源代码,那么 here 就是存储库的 link。对存储库的拉取请求也很受欢迎。如果你在存储库上,那么不要忘记切换到 react-material 分支。
P.S - 不要笑,因为我最近才开始使用 React :P
我克隆了你的分支并进行了测试,但我发现了一些有趣的东西:模拟方法在 ShallowWrapper 和 ReactWrapper 中的工作方式不同,即在使用 shallow 和使用 mount 时模拟工作不同。
首先看一下这个问题:
最适合这种测试的应该是shallow()而不是mount(),因为你是把这个组件作为一个单元来测试的。
测试挂载:
test("updateFilter should get called on simulating text changes in sources", () => {
const component = mount(<FiltersDesktop {...props} />);
component
.find(Select)
.at(0)
.props()
.onChange({ target: { value: 20 } });
expect(props.updateFilter).toHaveBeenCalled();
});
浅层测试:
test("updateFilter should get called on simulating text changes in sources", () => {
const wrapper = shallow(<FiltersDesktop {...props} />);
wrapper
.find(Select)
.at(0)
.simulate("change", { target: { value: 20 } });
expect(props.updateFilter).toHaveBeenCalled();
});
如您所见,在使用 shallow 的第二种方法中,我调用了变量包装器,因为它是组件的包装器,而不是组件,此外您可以注意到,在使用 mount 的第一种方法中,测试仅通过道具直接调用 onChange 时有效。
所以我开始使用 Jest 和 Enzyme 设置对由 Material-UI 组件组成的 React 组件进行单元测试。到目前为止,每个事件模拟都运行良好,直到我遇到来自 Material-UI 的 Select 组件。 (下面有更多信息)
项目使用 create-react-app 启动并利用 material-ui-next.
依赖版本
- 反应:16.2.0
- 反应-Dom:16.2.0
- 反应脚本:1.1.1
- Material UI: 1.0.0-beta.35
- Jest:随附安装包 (22.4.3)
- 酶:3.3.0
- 酶适配器 React 16:1.1.1
问题
我有一个名为 FiltersDesktop 的纯功能组件,由 Material-UI 表单字段组成。其中三个是 Select 组件,其他是来自 material-ui.
的文本字段和日期选择器UI代码
<Collapse in={props.visible} className={'filters-container-desk'}>
<Grid container classes={{ typeContainer: "filter-container" }} id={'container-desk'}>
<Grid item lg={2} xl={2}>
<FormControl fullWidth={true}>
<InputLabel htmlFor="sources">Sources</InputLabel>
<Select
open
inputProps={{ name: 'sources-desk', id: 'sources-desk' }}
value={props.filters.source || ''}
onChange={(event) => props.updateFilter({ source: event.target.value })}
>
<MenuItem value=''>
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item lg={2} xl={2}>
...
</Grid>
... // More Grid components of similar structure as above
</Grid>
</Collapse>
当我尝试在文本字段组件上模拟更改事件时,它工作正常。以下是我为测试文本字段而编写的代码:
TextField 的测试代码
const props = {
updateFilter: jest.fn()
};
test(`updateFilter should get called on simulating text changes in domain`, () => {
const component = mount(<FiltersDesktop {...this.props} />);
component.find('#domain-desk').last().simulate('change', { target: { value: 'scoopwhoop.com' } });
expect(props.updateFilter).toHaveBeenCalled();
});
但类似的东西不适用于 Select 组件。但是,当我通过界面实际与 Select 字段交互时,会调用更新函数。以下是我为了测试Select:
而写的测试代码Select
的测试代码const props = {
updateFilter: jest.fn()
};
test(`updateFilter should get called on simulating text changes in sources`, () => {
const component = mount(<FiltersDesktop {...this.props} />);
// Did not work
component.find('#sources-desk').last().simulate('change', { target: { value: 20 } });
// Did not work
component.find('Select').first().simulate('change', { taget: { value: 20 } });
// Did not work
component.find('#sources-desk').forEach(element => element.simulate('change', { taget: { value: 20 } }))
expect(props.updateFilter).toHaveBeenCalled();
});
由于某些原因,在上述所有情况下,find 方法总是返回超过 1 个元素,因此我在适当的情况下使用 first、last 和 forEach。
请帮助我找出在模拟 Select 组件时未触发更改事件的原因。
请放心,我至少花了一周时间阅读 Github 上的问题,尝试实施解决方案并测试 Jest 和 Enzyme 的 guides。我确信我的测试设置很好,因为其余情况都运行良好。
如果您想准确查看源代码,那么 here 就是存储库的 link。对存储库的拉取请求也很受欢迎。如果你在存储库上,那么不要忘记切换到 react-material 分支。
P.S - 不要笑,因为我最近才开始使用 React :P
我克隆了你的分支并进行了测试,但我发现了一些有趣的东西:模拟方法在 ShallowWrapper 和 ReactWrapper 中的工作方式不同,即在使用 shallow 和使用 mount 时模拟工作不同。
首先看一下这个问题:
最适合这种测试的应该是shallow()而不是mount(),因为你是把这个组件作为一个单元来测试的。
测试挂载:
test("updateFilter should get called on simulating text changes in sources", () => {
const component = mount(<FiltersDesktop {...props} />);
component
.find(Select)
.at(0)
.props()
.onChange({ target: { value: 20 } });
expect(props.updateFilter).toHaveBeenCalled();
});
浅层测试:
test("updateFilter should get called on simulating text changes in sources", () => {
const wrapper = shallow(<FiltersDesktop {...props} />);
wrapper
.find(Select)
.at(0)
.simulate("change", { target: { value: 20 } });
expect(props.updateFilter).toHaveBeenCalled();
});
如您所见,在使用 shallow 的第二种方法中,我调用了变量包装器,因为它是组件的包装器,而不是组件,此外您可以注意到,在使用 mount 的第一种方法中,测试仅通过道具直接调用 onChange 时有效。