在我的 react 组件中,我有一个元素在 5 秒后出现。
我想做一个测试,用 jest fake timers
检查元素是否在 5 秒后出现,但无法使其工作...
我在这里做错了什么?
其中一个示例不起作用:
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();
});
});
第二个例子:
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();
});
最佳答案
使用 await findBy
查询和 await waitFor
的一般经验法则是您应该使用
await findBy
when you expect an element to appear but the change to the DOM might not happen immediately.
and
await waitFor
when you have a unit test that mocks API calls and you need to wait for your mock promises to resolve.
dom-testing-library的官方文档中也提到了同样的事情.
现在,您需要使用 jest.useFakeTimer()
来启用假计时器,这将有助于模拟 setTimeout 和其他计时器函数。
official docs 中也提到了同样的情况.
useFakeTimer 与 async methods 配合使用但是,如果我们想要使用像 getBy
查询这样的同步方法,那么我们必须使用 jest.advanceTimersByTime(5000)
将测试移动 5(任何指定时间)秒在它前面。 (下面给出的示例)
在下面的示例中,我重现了您提出的问题。我认为这可能会有所帮助。
import { useState } from 'react';
import { act, render, screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
const data = {
name: 'subrato',
age: 24,
};
function App() {
const [myData, setState] = useState({});
const [loading, setLoading] = useState(false);
function clickHandler() {
setLoading(true);
setTimeout(() => {
setState(data);
setLoading(false);
}, 5000);
}
return (
<div className='App'>
{loading && <div aria-label='loading'>loading....</div>}
<p>{myData?.name}</p>
<p>{myData?.age}</p>
<button onClick={clickHandler}>Click me</button>
</div>
);
}
describe('Test my app', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it('display data', async () => {
render(<App />);
userEvent.click(screen.getByText('Click me'));
expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();
expect(await screen.findByText('subrato')).toBeInTheDocument();
expect(screen.getByText('24')).toBeInTheDocument();
});
it('display data second time', async () => {
render(<App />);
userEvent.click(screen.getByText('Click me'));
expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();
act(() => jest.advanceTimersByTime(5000));
expect(screen.getByText('subrato')).toBeInTheDocument();
expect(screen.getByText('24')).toBeInTheDocument();
});
});
测试结果
PASS src/TimerExample.spec.tsx (9.001 s)
Test my app
√ display data (487 ms)
√ display data second time (35 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 14.997 s
Ran all test suites matching /TimerExample.spec.tsx/i.
关于javascript - 如何进行一个在检查元素外观之前等待 5 秒的测试(React 测试库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70876086/