Этот ответ весьма специфичен c для реагирования-тестирования-библиотеки, но я думаю, что концепция в целом применима.
Прежде всего я понял, что если вы запустите операцию asyn c в ответ на пользовательское событие (скажем, щелчок), тогда у вас нет проблем - как только вы позвонили fireEvent.click
, вы находитесь в состоянии 3, тогда вы можете использовать waitFor()
, чтобы дождаться перехода в состояние 4.
Во-вторых, если ваша среда дает вам справку об обещании операции asyn c, тогда, конечно, вы можете просто подождать этого, чтобы снова у вас не возникло проблем.
В моем случае операция asyn c была запущена таймером, и, поскольку она находилась внутри реагирующего компонента, я получаю ручку для этого таймера извне. Итак, мой сценарий выглядит примерно так:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { message: "initial" };
}
componentDidMount = () => setTimeout(async () => {
this.setState({ message: "loading" });
var message = await this.props.longRunningOperation();
this.setState({ message });
}, 5000);
render = () => <div>{this.state.message}</div>
}
Состояние компонента изначально «начальное», через 5 секунд после его монтирования, оно запускает длительную операцию и устанавливает состояние «загрузка», затем, когда он получает ответ, он устанавливает состояние для текста этого ответа. Мой тестовый пример выглядит так:
test("long running response", async () => {
const fakeLongRunningOperation = async () => new Promise(resolve =>
setTimeout(() => resolve("success"), 2000));
jest.useFakeTimers();
var app = render(<App longRunningOperation={fakeLongRunningOperation} />);
jest.advanceTimersByTime(4000)
expect(app.queryByText("initial")).not.toBeNull();
jest.advanceTimersByTime(2000)
expect(app.queryByText("loading")).not.toBeNull();
jest.advanceTimersByTime(2000)
await waitFor(() => { expect(app.queryByText("success")).not.toBeNull() });
});
Мы подделываем длительную операцию с функцией, которая возвращает «успех» после 2-секундной задержки. Через 4 секунды мы ожидаем, что состояние все еще будет «начальным», затем еще через 2 секунды мы ожидаем, что оно «загружается», и еще через 2 секунды мы ожидаем, что оно будет «успешным». И мы используем фальшивые таймеры, чтобы на самом деле тест не занимал 8 секунд.
Надеюсь, что это поможет любому, кто пытается сделать нечто подобное.