1

I am trying to use mock service worker to intercept a response from an endpoint and then modify one field of that json response. If we have an endpoint /user that returns a json looking like

users: [{
  user: {
    name: John,
    age: 31,
    occupation: Engineer
  }
}]

I would like to be able to intercept the response from within msw post and change the occupation to be "Student"

So, I believe my handler should return something where it manipulates res?

rest.post('*/users', (req, res, ctx) => {
  return res((res) => {
    ????
  }
}

This general idea wouldn't work because the response mocked response body is Null?

  • If you're mocking out you're not _hitting_ the real endpoint (which is the point, then your tests can run much faster). Why not just respond with exactly what you want? – jonrsharpe Aug 12 '22 at 16:55
  • @jonrsharpe for a couple of reasons: first off, I want the rest of the information that the endpoint provides (i.e. I want age and name from the endpoint but I want to be able to manipulate occupation). Also, this response is directly used in another script, so I cannot just manipulate the response directly – juliamartin27 Aug 12 '22 at 17:04

2 Answers2

1

Response Patching probably allows what I think you're describing.

You can write something like the following:

rest.post('*/users', async (req, res, ctx) => {
    const originalResponse = await ctx.fetch(req)
    const originalResponseData = await originalResponse.json() 
    // if you like TypeScript you can add to the previous line
    // as {name: string, age: number, occupation: string}
    // or use a defined type.

    return res(
      ctx.json({
        ...originalResponseData,
        occupation: 'Student',
      }),
    )
})

or since your post actually had arrays, maybe:

rest.post('*/users', async (req, res, ctx) => {
    const originalResponse = await ctx.fetch(req)
    const originalResponseData = await originalResponse.json() as {occupation: string, name: string, age: number}[]

    // Make all returned users Students, or whatever you need here...
    const modifiedResponse = originalResponseData.map((user) => {
        return {
            ...user,
            occupation: 'Student'
        }
    })
    return res(ctx.json(modifiedResponse))
}),
chrisb2244
  • 2,940
  • 22
  • 44
  • If you need to fetch the actual data (not mocked), response patching is the way to go. This looks like the right answer. – kettanaito Oct 16 '22 at 23:13
0

Take a look at Conditional response and Include failure scenarios of MSW.

The mock response depends on the request. We can return different mock responses based on request url parameters. We can add a testcase url parameter to the endpoint of the mock handler, use this control the handler returns the different mock responses.

E.g.

rest.post('*/users', (req, res, ctx) => {
  return res(
    ctx.json({
      users: [
        {
          user: {
            name: 'John',
            age: 31,
            occupation: req.url.searchParams.get('testcase') === 'student' ? 'Student' : 'Engineer',
          },
        },
      ],
    }),
  );
});
Lin Du
  • 88,126
  • 95
  • 281
  • 483