So far, in the projects I'm working on, I usually snapshot-test my components that does async data loading this way:
describe('MyComponent component', () =>{
test('Matches snapshot', async () => {
fetch.mockResponse(JSON.stringify(catFacts));
const { asFragment } = render(<MyComponent />);
await waitFor(() => expect(asFragment()).toMatchSnapshot());
})
})
I find it very handy, because it allows to have a snapshot containing the different states of the component (loading, errors, loaded data).
The thing is that I just found out that this method was not recommended at all, and that the latest updates of the @testing-library/react package don't allow me to test my components this way anymore.
According to the eslint rules of the package, I would have to modify my code like this:
describe('MyComponent component', () =>{
test('Matches snapshot', () => {
fetch.mockResponse(JSON.stringify(catFacts));
const { asFragment } = render(<MyComponent />);
expect(asFragment()).toMatchSnapshot();
})
})
It works, but the generated snapshot contains only the initial state of the component (in this case, "loading").
How would you do in this situation to efficiently snapshot-test a component loading data asynchronously?
You are on the right track. The only thing left is to wait for your data to be loaded before you make your assertion.
describe('MyComponent component', async () =>{
test('Matches snapshot', () => {
fetch.mockResponse(JSON.stringify(catFacts));
const { asFragment } = render(<MyComponent />);
await waitForElementToBeRemoved(screen.getByText('loading'));
expect(asFragment()).toMatchSnapshot();
})
})
I used the loading
text since you mentioned it on your question. But you can also wait for your data to appear on screen:
await screen.findByText('something that comes from the mocked data');
Great job on noticing the waitFor
issue and fixing it!