Testing in-progress state after user-event #911
-
Hello, I have a lot of tests, that cover in-progress states after actions (e.g. click) and before the async method (e.g. api call) is resolved. Example // Component.js
...
onClick = () => {
setLoading();
reloadData().then(data => setData(data));
}
... Before // Test.test.js
...
reloadData = jest.fn().mockResolvedValue(data);
userEvent.click(component)
expect(screen.getByRole('progressrole')).toBeInTheDocument();
await waitFor(....)
... But because all user events are now returned as promises, it immediately resolves the async request too, so it is not possible to check the in-between state: After // Test.test.js
...
reloadData = jest.fn().mockResolvedValue(data);
await userEvent.click(component)
??? expect(screen.getByRole('progressrole')).toBeInTheDocument(); ???
... Is there a way how to test the in-progress state without using setTimeouts in the mocked async methods? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
The Promise returned by One way to test such things is to // Get a Promise and the callback to resolve it
let resolveWaitForLoadingState = () => {}
const waitForLoadingState = new Promise(r => { resolveWaitForLoadingState = r })
// Resolve the Promise when the mock puts your component in the state to be observed
reloadData = jest.fn(() => {
resolveWaitForLoadingState()
return data
})
// Start the click simulation and wait for the right moment to run your assertion
await Promise.all([
user.click(element),
waitForLoadingState.then(() => { expect(screen.getByRole('progressrole')).toBeInTheDocument() }),
}) Another is to implement the // Let `reloadData` take 5ms
reloadData = jest.fn(async () => {
await new Promise(r => setTimeout(r, 5))
return data
})
await user.click(element)
// Still 5ms of reloading data ...
expect(screen.getByRole('progressrole')).toBeInTheDocument() A third way is to control when your mock resolves from outside: let resolveReloadingData = () => {}
reloadData = jest.fn(() => new Promise(r => { resolveReloadingData = r })
await user.click(element)
expect(screen.getByRole('progressrole')).toBeInTheDocument()
resolveReloadingData(data) |
Beta Was this translation helpful? Give feedback.
The Promise returned by
.click()
resolves when the library is done simulating the interaction.The asynchronous request is not resolved instantly, just before this is finished.
One way to test such things is to
await
the state you want to test on: