How to conditionally mock error responses with msw

Viewed 2210

The UI I'm working on is rendered differently based on the response received. I would like to test the UI when a 4xx and 5xx responses are received.

My api handler looks something like:

import { rest } from 'msw';
import { items } from './apiValues';

export const handlers = [
  rest.get('/items/', (_req, res, ctx) => res(ctx.status(200), ctx.json(items))),
];

This will always return a 2xx response making it unable to test the UI if a 4xx or 5xx response is received, unless I change the handlers manually, which is tiring.

How can tests for 4xx and 5xx responses be tested?

2 Answers

Use search parameters to control the response for the get request.

Pass a variable in req.body to control if the response is successful or not for the post request.

See Conditional response

import { setupWorker, rest } from 'msw';

const worker = setupWorker(
  rest.get('/items/', (req, res, ctx) => {
    const error = req.url.searchParams.get('error')
     
    // error response
    if(error === 'network') {
      return res(
        ctx.status(400),
        ctx.json({
          errorMessage: 'Network error',
        }),
      )
    }

    // successful response
    return res(ctx.status(200), ctx.json(items));
  }),
)

If you don't want to mess with query params, you can also use the .use() function.

  1. Wherever you set up your handlers, add another array for each condition you want to test for
export const errorHandlers = [
  rest.get('/items/', (_req, res, ctx) => res(ctx.status(500), ctx.json(null))),
];
  1. In your test file, import the handlers and the msw server you have set up, then inside the test, spread in the handlers in the server instance you want to use.
import { errorHandlers } from './handlers'
import { mswServer } from 'setupTests'

test('handles errors', () => {
  mswServer.use(...errorHandlers)
  // ...the rest of your test  
})
Related