5

I have a simple list of homes generated with RTK query hooks where item can be marked favorite and data refetched automatically based on tags invalidation. While everything works when I run the project within the test msw is not able to match the same GET request called second time after mutation success triggers it via tags invalidation.

service:

export const homesApi = createApi({
reducerPath: 'homesApi',
baseQuery: fetchBaseQuery({
  baseUrl: API_URL,
  prepareHeaders: (headers, { getState }) => {
    headers.set('Accept', `application/json`);
    return headers;
  },
}),
tagTypes: [
  'Homes',
],
endpoints: (builder) => ({
  getHomes: builder.query({
    query: (params) => {
      
      const url = qs.stringifyUrl(
        { url: '/homes', query: params },
        { skipEmptyString: true, skipNull: true }
      );

      return url

    },
    providesTags: (result) =>
      result?.data
        ? [
            ...result.data.map(({ id }) => ({ type: 'Homes', id })),
            { type: 'Homes', id: 'LIST' },
          ]
        : [{ type: 'Homes', id: 'LIST' }],
  }),
  homeFavorite: builder.mutation({
    query(payload) {

      const {id} = payload;
      const url = `/homes/${id}/favorite`;

      return {
        url,
        method: 'POST'
      };

    },
    invalidatesTags: () => [{ type: 'Homes', id: 'LIST' }],
  }),
}),
});

export const {
  useGetHomesQuery,
  useHomeFavoriteMutation
} = homesApi;

test:

const store = configureStore({
  reducer: {
    [homesApi.reducerPath]: homesApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
   getDefaultMiddleware({
      serializableCheck: false,
      immutableCheck: false,
   }).concat(
      homesApi.middleware
   ),
});

setupListeners(store.dispatch);

let cleanupListeners;

describe('Homes component', () => {
    beforeEach(() => {
        cleanupListeners = setupListeners(store.dispatch)
    })

    afterEach(() => {
        cleanupListeners();
        store.dispatch(homesApi.util.resetApiState())
    });

    it('should mark item favorite', async() => {
     
       server.use(
          rest.get(`${API_URL}/homes`, (req, res, ctx) => {
            return res(
              ctx.json(MOCK_SUCCESS)
            );
          }), 
          rest.post(`${API_URL}/homes/1/favorite`, (req, res, ctx) => {
            return res(
              ctx.json({})
            );
          }),
        );

      render(
        <Provider store={store}>
            <BrowserRouter>
                <Routes>
                    <Route path={'/'} element={<Homes/>}/>
                </Routes>
            </BrowserRouter>
        </Provider>
      );

      const user = userEvent.setup();
      const items = await screen.findAllByTestId('homeItem');

      expect(items.length).toBe(5);

      const icon = within(items[0]).getByTestId('fIcon');

      expect(icon).not.toHaveClass('fav');
    
      await user.click(icon);

     //here I try to match the request for the second time with new data
      server.use(
        rest.get(`${API_URL}/homes`, (req, res, ctx) => {
            return res(
              ctx.json(MOCK_SUCCESS_UPDATED)
            );
        }), 
      )

      const itemsNew = await screen.findAllByTestId('homeItem');

      expect(within(itemsNew[0]).getByTestId('fIcon')).toHaveClass('fav');
      
    })
});

any idea what am I doing wrong since I am not able to match the same GET request for the second time no matter what I try. below is the error I am getting

[MSW] Warning: captured a request without a matching request handler:

user1751287
  • 491
  • 9
  • 26

1 Answers1

0

try out with

https://mswjs.io/docs/api/response/once

basic idea that res.once mock response for exactly 1 api call

if you call the same endpoint twice, it will only respond once

here is my use case, I fetch data, i then run a post request to add data, then i need to refetch the data so that the updated data is present in UI,

try with no global handler, and in your test, do:

server.use(
  rest.get('your/endpoint', (req, res, ctx) => 
    res.**once**(ctx.json(replaceDataHereWithDesiredResponse))
  )
)

twice, of course, above codes were in the same test clause

Labithiotis
  • 3,519
  • 7
  • 27
  • 47
Sean
  • 1
  • 1