reactjstestingjestjsreact-testing-libraryswr

SWR Test Mutation


What is a recommended way of testing mutation from SWR?

function Index() {
  const { data, mutate } = useSWR("/api/user", fetch);

  if (data.loggedIn) {
    return (
      <Button
        onClick={() => {
          logout();
          mutate(); // after logging in/out, we mutate the SWR
        }}
      >
        Logout
      </Button>
    );
  } else {
    // login
    return (<h1>Please login</h1>)
  }
}

Related to discussion: https://github.com/vercel/swr/discussions/2434

If we have given flow logout -> mutate swr -> show login form

I think we shouldn't test implementation details and instead test what user actually see after mutation/change happened?

expect(mutate).toHaveBeenCalled('/logout'); // bad 
expect(screen.getByText('Please login')).toBeInTheDocument(); // correct

What is the general feeling about this?


Solution

  • This should work, however you want to consider to mock the fetch instead.

    import { useSWRConfig } from 'swr';
    
    // FIXME: tests should be mocking the fetch instead
    // https://dev.to/bmvantunes/please-don-t-mock-swr-fetch-or-axios-in-your-unit-integration-tests-521k
    jest.mock('swr', () => ({
      ...jest.requireActual('swr'),
      useSWRConfig: jest.fn(() => ({
        mutate: () => {},
      })),
    }));
    
    it('should mutate data', async () => {
      const mockMutate = jest.fn();
    
      useSWRConfig.mockImplementationOnce(() => ({ mutate: mockMutate }));
    
      expect(mockMutate).toHaveBeenCalledWith('swrKey');
      ...
    });