我正在我的 React 应用程序中使用 Jest 和 RTL 测试用户点击交互。组件状态通过交互(即单击事件)进行更新。
我的组件有一个组合框,单击它时,应该打开列表框并显示选项。
test.only('option should open when clicked', async () => {
// Arrange
const props = {
searchProcessing: false,
setSearchProcessing: () => {},
setFilterInfo: () => {},
setData: () => {},
sortBy: {
FieldName: 'state',
Direction: 'ASC',
},
pageNumber: 1,
pageSize: 10,
};
// Act
await act(async () => {
await render(<Component{...props} />);
const combobox = await screen.findByRole('combobox', { owns: 'select-state' });
fireEvent.click(combobox);
});
const options = within(screen.getByRole('listbox')).getAllByRole('option');
screen.debug(options);
// Assert
expect(options).toHaveLength(2);
});
当我运行上面的代码时,它抛出一个错误
Unable to find role="combobox"
Ignored nodes: comments, script, style
<body>
<div />
</body>
await act(async () => {
23 | await render(<Component {...props} />);
> 24 | combobox = await screen.findByRole('combobox', { owns: 'select-state' });
| ^
25 | });
当我将
fireEvent
放入 waitFor
异步方法中,插入 act
时,就像下面的代码片段一样,它正在工作。
await waitFor(() => {
fireEvent.click(screen.getByRole('combobox', { owns: 'select-state' }));
});
console.log
<a
aria-label="AK"
aria-selected="false"
class="dropdown-item"
href="#"
id="select-state-item-0"
role="option"
>
AK
</a>
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:94:13)
at Array.forEach (<anonymous>)
console.log
<a
aria-label="AK2"
aria-selected="false"
class="dropdown-item"
href="#"
id="select-state-item-1"
role="option"
>
AK2
</a>
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:94:13)
at Array.forEach (<anonymous>)
PASS src/App/Main/Component.test.js (11.508 s)
√ state option should open when clicked (454 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 16.5 s
no-wait-for-side-effects
这是一个不好的做法。
__
我应该错过什么?为什么我的
render
和 findByRole
承诺不在 act
函数中等待实际的组件 DOM。但相同的代码通过了 waitFor
在此感谢您的任何帮助。预先感谢。
经过多次尝试和错误,我找到了两种可能的解决方案。
将第二个动作/事件包装在另一个动作中
await act(async () => {
await render(<Component {...props} />);
});
await act(async () => {
fireEvent.click(await screen.findByRole('combobox', { owns: 'select-state' }));
});
RTL 正在证明另一个实用程序 userEvent。您可以使用它代替 fireEvent,如下所示。
const user = userEvent.setup();
await user.click(await screen.findByRole('combobox', { owns: 'select-state' }));
希望有帮助。谢谢。