xjinx
xjinx

Reputation: 195

Jest Snapshot Testing Wait till Component Renders

I feel like I am missing something when it comes to testing React components with async fetch operations.

I have a following component like this...

export default function Page() {
    const [result, setResult] = useState();

    async function initialize() {
       const response = api.fetchData();
       setResult(response);
    }

    useEffect(() => {
        initialize();
    }, []);

    return (isLoading ? (
        <div>Fetching Data...</div>
    ) : (
        <div className="page-result-name">{result.name}</div>
    )
}

I want to create the following test.

test('Page rendering test.', async () => {
    jest.spyOn(api, 'fetchData').mockResolvedValue({ name: 'User 1'});

    const pageRendering = renderer.create(<Page />);

    // Wait?  How to wait?
    // I have tried the following... as well as other method.
    // await waitFor(() => {
    //     const element = document.getElementByClassName('page-result-name')[0] as 
    //     HTMLElement;
    //     expect(element.innerHTML.includes('User 1')).toBeTruthy();
    // });

    expect(pageRendering.toJSON()).toMatchSnapshot();
});

The issue I am running into is that the data has not been returned by the time the snapshot is taken.

Regardless of the approach I run into issues with warnings like the following

Warning: It looks like you're using the wrong act() around your test interactions

Or it always displays Fetching Data...

I have used render from @testing-library/react and the waitFor and things work well. I don't know how to generate a snapshot for that.

Any help here would be appreciated!!

Cheers!!

Upvotes: 2

Views: 1996

Answers (1)

Joel
Joel

Reputation: 1064

For async operations the tricky is waiting for loading component to be removed from the screen, this way you assure that the your component is completed loaded and then you can expect the snapshot:

test('Page rendering test.', async () => {
    jest.spyOn(api, 'fetchData').mockResolvedValue({ name: 'User 1'});

    const pageRendering = renderer.create(<Page />);

    // Wait?  How to wait?
    //  wait for your data to be loaded before you make your assertion.
    await waitForElementToBeRemoved(screen.getByText('Fetching Data...'));

    expect(pageRendering.toJSON()).toMatchSnapshot();
});

Upvotes: 1

Related Questions