Getting request body of mock service worker and react testing library
Asked Answered
A

2

8

So i am writing tests for one of my react projects and i just decided to use mock service worker to mock my api calls and i am trying to mock a login endpoint.So i am trying to simulate a login error where i return an error message when the input does not match a particular email. Given the code below;

const server = setupServer(
  rest.post("https://testlogin.com/api/v1/login", (req, res, ctx) => {
    // the issue is getting the email from the request body something like the code just below
    if (req.body["email"] != "[email protected]") {
      ctx.status(401);
      return res(
        ctx.json({
          success: false
        })
      );
    }
  })
);

How can i do that? Is there a better way to do that?

Arioso answered 30/11, 2021 at 8:8 Comment(0)
S
13

Edit: MSW 2.0

Since the release of MSW 2.0, the way you operate with request/response bodies is the same now as you do with Fetch API.

import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'

setupServer(
  http.post('/endpoint', async ({ request }) => {
    const data = await request.formData()
    const email = data.get('email')
  
    if (email !== '[email protected]') {
      return HttpResponse.json({ success: false }, { status: 401 })
    }

    return HttpResponse.json({ success: true })
  })
)

In this example, I read the request body as FormData. You can also read it as .json(), .text(), etc.—those are the regular Request instance methods.

Learn more about the new version of MSW and also How to migrate from 1.x to 2.x.

MSW 1.0

You should be able to get the req.body.email value given your request sets the Content-Type: application/json header. Without the Content-Type header, neither MSW nor your actual server could know what kind of data you're attempting to send (if anything, it can be a binary!). By providing the correct Content-Type header you form a correct request but also let MSW be sure that req.body should be parsed to an object.

// your-code.js
fetch('https://testlogin.com/api/v1/login', {
  method: 'POST',
  headers: {
    // Adding this header is important so that "req.body"
    // is parsed into an object in your request handler.
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ login: '[email protected]' })
})
// your-handlers.js
rest.post('https://testlogin.com/api/v1/login', (req, res, ctx) => {
  const { login } = req.body

  if (login !== '[email protected]') {
    return res(ctx.status(401), ctx.json({ success: false }))
  }

  return res(ctx.json({ success: true }))
})

Note how the ctx.status(401) call is inside the res() function call. Calling any ctx[abc] methods outside of res will result in no effect as they rely on being wrapped in res.

Sauder answered 4/12, 2021 at 0:51 Comment(3)
req.body() is now deprecated, if your body has JSON data you can use req.json() (docs)Caucus
the body looks empty for me and I added the Content-TypeDeposal
Thanks for the MSWv2 section. request.json() worked for me when request.formData() did not. You helped me solve a big headache.Stutsman
R
1

In the latest version, you can use .json()

from official documentation

    // src/mocks/handlers.js
import { http, HttpResponse } from 'msw'
 
const allPosts = new Map()
 
export const handlers = [
  http.post('/posts', async ({ request }) => {
    // Read the intercepted request body as JSON.
    const newPost = await request.json()
 
    // Push the new post to the map of all posts.
    allPosts.set(newPost.id, newPost)
 
    // Don't forget to declare a semantic "201 Created"
    // response and send back the newly created post!
    return HttpResponse.json(newPost, { status: 201 })
  }),
]
Ropy answered 20/9 at 13:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.