Msw: How should I use the service worker in jest?

Created on 19 May 2020  路  2Comments  路  Source: mswjs/msw

I'm planning to use this for tests only, so where should I put my serviceWorker file and how will it communicate with my component?

this is the code I'm running for my test (simplified), my component execute some data fetching on mount, this is breaking the test with window.fetch is not defined.

/**
 * External dependencies
 */
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import { render, fireEvent, waitFor, screen } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import { CartProvider } from './base-context';
/**
 * Internal dependencies
 */
import CartSidebar from '../cart-sidebar';

describe('CartSidebar', () => {
    const server = setupServer(
        rest.get('*', (req, res, ctx) => {
            return res(ctx.json({ firstName: 'John' }))
        })
    )

  beforeAll(() => {
    // Enable the mocking before all tests
    server.listen()
  })

  it('should render the cart sidebar ', async () => {
    render(
        <CartProvider>
            <CartSidebar />
        </CartProvider>
    )
    const title = screen.getAllByRole('heading');
    expect(title[0].textContent).toEqual('Cart totals')
  })
})
bug

Most helpful comment

Hey, @senadir.

As Service Workers cannot run in a non-browser environment, you don't need to have a Service Worker file if you are planning to use MSW only for Jest tests.

I highly recommend to run server.close() in the afterAll hook of your test file:

const server = setupServer(...)

beforeAll(() => server.listen())
afterAll(() => server.close())

This makes sure that the patched instances are restored, and the mocked state does not transition to unrelated tests.

The window.fetch is not defined error you are experiencing is most likely because fetch doesn't exist in Node, so Jest cannot work with your component that calls fetch(). This is an expected behavior, and you would have to provide a fetch polyfill of your choice. Here are some of the worthy mentions:

Pick any of those and require them in your jest.setup.js file:

// jest.setup.js
// This ensures you can use `window.fetch()` in your Jest tests.
require('whatwg-fetch')

Then provide the path to that setup file in your jest.config.js file using the setupFiles option:

// jest.config.js
module.exports = {
  setupFiles: ['./jest.setup.js']
}

Let me know if these suggestions helped. I'm closing this, because it doesn't look like an issue with MSW.

All 2 comments

Hey, @senadir.

As Service Workers cannot run in a non-browser environment, you don't need to have a Service Worker file if you are planning to use MSW only for Jest tests.

I highly recommend to run server.close() in the afterAll hook of your test file:

const server = setupServer(...)

beforeAll(() => server.listen())
afterAll(() => server.close())

This makes sure that the patched instances are restored, and the mocked state does not transition to unrelated tests.

The window.fetch is not defined error you are experiencing is most likely because fetch doesn't exist in Node, so Jest cannot work with your component that calls fetch(). This is an expected behavior, and you would have to provide a fetch polyfill of your choice. Here are some of the worthy mentions:

Pick any of those and require them in your jest.setup.js file:

// jest.setup.js
// This ensures you can use `window.fetch()` in your Jest tests.
require('whatwg-fetch')

Then provide the path to that setup file in your jest.config.js file using the setupFiles option:

// jest.config.js
module.exports = {
  setupFiles: ['./jest.setup.js']
}

Let me know if these suggestions helped. I'm closing this, because it doesn't look like an issue with MSW.

Here's a usage example repository that showcases how to use MSW for both unit (Jest) and E2E tests. You may not need the entire setup, but I'm sure you can find some useful references there.

Note that it uses Create React App, which provides a fetch polyfill out of the box. In case of manual Jest setup one needs to do that manually.

Was this page helpful?
0 / 5 - 0 ratings