Mar*_*mes 2 javascript unit-testing reactjs jestjs react-testing-library
在我的反应组件中,我有一个 5 秒后出现的元素。
我想做一个测试,检查 5 秒后元素是否出现jest fake timers,但无法使其工作......
我在这里做错了什么?
其中一个示例不起作用:
it('check step 2 labels text, status "Submitted"', async () => {
render(<ProgressIndicator appStatus="submitted" />);
jest.advanceTimersByTime(5005);
await waitFor(() => {
expect(
screen.getByText('Beep. Boop. Still doing our thing here.'),
).toBeInTheDocument();
});
await waitFor(() => {
expect(screen.getByText('Verifying identity...')).toBeInTheDocument();
});
});
Run Code Online (Sandbox Code Playgroud)
第二个例子:
it('check step 2 labels text, status "Submitted"', async () => {
render(<ProgressIndicator appStatus="submitted" />);
act(() => {
jest.advanceTimersByTime(5005);
});
expect(
screen.getByText('Beep. Boop. Still doing our thing here.'),
).toBeInTheDocument();
expect(screen.getByText('Verifying identity...')).toBeInTheDocument();
});
Run Code Online (Sandbox Code Playgroud)
await findBy使用查询的一般经验法则await waitFor是您应该使用
\n\n\n
await findBy当您期望出现某个元素但 DOM 的更改可能不会立即发生时。
\n\n当
\nawait waitFor你有一个模拟 API 调用的单元测试时,你需要等待你的模拟承诺解析。
dom-testing-library的官方文档中也提到了同样的内容。
\n现在谈到您关心的问题,您需要使用jest.useFakeTimer()启用假计时器,这将有助于模拟 setTimeout 和其他计时器函数。
官方文档中也提到了同样的事情。
\nuseFakeTimer 使用异步方法,但是,如果我们想要使用getBy查询等同步方法,那么我们必须使用jest.advanceTimersByTime(5000)将测试提前 5(任何指定时间)秒。(下面给出的例子)
在下面的例子中,我重现了您提出的问题。我想这可能会有所帮助。
\nimport { useState } from \'react\';\nimport { act, render, screen, waitForElementToBeRemoved } from \'@testing-library/react\';\nimport userEvent from \'@testing-library/user-event\';\n\nconst data = {\n name: \'subrato\',\n age: 24,\n};\n\n\nfunction App() {\n const [myData, setState] = useState({});\n const [loading, setLoading] = useState(false);\n\n function clickHandler() {\n setLoading(true);\n setTimeout(() => {\n setState(data);\n setLoading(false);\n }, 5000);\n }\n\n return (\n <div className=\'App\'>\n {loading && <div aria-label=\'loading\'>loading....</div>}\n <p>{myData?.name}</p>\n <p>{myData?.age}</p>\n <button onClick={clickHandler}>Click me</button>\n </div>\n );\n}\ndescribe(\'Test my app\', () => {\n beforeEach(() => {\n jest.useFakeTimers();\n });\n\n afterEach(() => {\n jest.useRealTimers();\n });\n\n it(\'display data\', async () => {\n render(<App />);\n\n userEvent.click(screen.getByText(\'Click me\'));\n\n expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();\n\n expect(await screen.findByText(\'subrato\')).toBeInTheDocument();\n expect(screen.getByText(\'24\')).toBeInTheDocument();\n \n });\n\n it(\'display data second time\', async () => {\n render(<App />);\n\n userEvent.click(screen.getByText(\'Click me\'));\n\n expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();\n\n act(() => jest.advanceTimersByTime(5000));\n\n expect(screen.getByText(\'subrato\')).toBeInTheDocument();\n expect(screen.getByText(\'24\')).toBeInTheDocument();\n \n });\n});\nRun Code Online (Sandbox Code Playgroud)\n测试结果
\n PASS src/TimerExample.spec.tsx (9.001 s)\n Test my app\n \xe2\x88\x9a display data (487 ms)\n \xe2\x88\x9a display data second time (35 ms)\n\nTest Suites: 1 passed, 1 total\nTests: 2 passed, 2 total\nSnapshots: 0 total\nTime: 14.997 s\nRan all test suites matching /TimerExample.spec.tsx/i.\nRun Code Online (Sandbox Code Playgroud)\n