What is the proper way to capture a HTTP response with Puppeteer?

If you need to manipulate the request/response, use page.setRequestInterception(true) and page.on/page.once (as documented).

However, if all you need is to assert something about the response, the simplest and most idiomatic way to do so is with page.waitForResponse:

const updateDashboardResponse = await page.waitForResponse(response =>
  response.url().includes('updateDashboard')
);
expect(updateDashboardResponse.status()).toBe(200);

This allows test flow to remain linear and avoids ambiguity around closing a test before a page.on handler receives a response event.


I believe you should do something along those lines. Note the callback function done.

What the code does, is that it attaches a listener for responses, then clicks the submit button. When a response is received it checks the status code, asserts it, and terminates the test by calling done.

You might want to have an if-statement that checks that it is the actual response from your form that you are checking in the callback, as the response handler might emit events for other concurrent requests.

it.only('returns a 400 response if email is taken', () => {
  await page.goto(`${process.env.DOMAIN}/sign-up`)
  await page.waitFor('input[id="Full Name"]')

  await page.type('input[id="Full Name"]', 'Luke Skywalker')
  await page.type('input[id="Email"]', '[email protected]')
  await page.type('input[id="Password"]', 'LukeSkywalker123', {delay: 100})

  page.on('response', (response) => {
    if (
      response.request().method === 'POST' && 
      response.url === `${process.env.USERS_API_DOMAIN}/sessions`) 
    {
      expect(response.status).toEqual(400)
    }
  })

  await page.click('input[type="submit"]', {delay: 1000})
})

I have not tested the code, but it should give you the right idea.

Edit: Adjusted to reflect what worked out in the end.