heroPhoto by Sarah Kilian on Unsplash

How to fix Jest and Mock Service Worker integration errors

In a recent project, my team decided to use Mock Service Worker (MSW) in our unit tests. It was meant to be a very straightforward change since the documentation for MSW is pretty clear. I encountered a few errors along the way that had me scratching my head. I'm going to document them here, hopefully will help people in a similar situation.

This is what we had before the change:

// jest.config.js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.build.json',
    },
  },
};

Integrating with MSW

Following the official guide here, I created server.ts and jest.setup.ts files.

// src/mocks/server.ts

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

// This configures a request mocking server with the given request handlers.
export const server = setupServer(...handlers);
// jest.setup.js

import { server } from './src/mocks/server';

beforeAll(() => {
  // Enable the mocking in tests.
  server.listen();
});

afterEach(() => {
  // Reset any runtime handlers tests may use.
  server.resetHandlers();
});

afterAll(() => {
  // Clean up once the tests are done.
  server.close();
});

Then I just had to reference the setup file in jest.config.js.

// jest.config.js
module.exports = {
  ...
  setupFilesAfterEnv: ['./jest.setup.ts'],
};

The handler is directly relevant to what is being explained here. But if you are interested, the handlers file looks something like this:

// src/mocks/handlers.ts

export const handlers = [
  rest.get('https://api.backend.dev/user', (req, res, ctx) => {
    return res(ctx.json({ firstName: 'John' }))
  }),
];

Issue 1 - can't find module 'typescript'

After the integration with MSW was done, I saw this error when I tried to run the jest tests. It is very strange because I changed nothing and it suddenly complains typescript doesn't exist.

Error: Cannot find module 'typescript'
Require stack:
- /Users/hao/node_modules/ts-jest/dist/config/config-set.js
- /Users/hao/node_modules/ts-jest/dist/ts-jest-transformer.js
- /Users/hao/node_modules/ts-jest/dist/index.js
- /Users/hao/demo-project/node_modules/jest-util/build/requireOrImportModule.js
- /Users/hao/demo-project/node_modules/jest-util/build/index.js
- /Users/hao/demo-project/node_modules/@jest/core/build/cli/index.js
- /Users/hao/demo-project/node_modules/@jest/core/build/jest.js
- /Users/hao/demo-project/node_modules/jest-cli/build/cli/index.js
- /Users/hao/demo-project/node_modules/jest-cli/bin/jest.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
    at Function.Module._load (internal/modules/cjs/loader.js:746:27)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (/Users/hao/node_modules/ts-jest/dist/config/config-set.js:58:20)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Module.require (internal/modules/cjs/loader.js:974:19)

error Command failed with exit code 1.

After some digging around, it appears this error is actually complaining about ts-jest is missing in the dependencies. See original stackoverflow question.

Issue 2 - non-standard JavaScript syntax

After installing ts-jest as a dev-dependency, I got yet another error.

● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/hao/demo-project/jest.setup.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { server } from './src/mocks/server';
                                                                                     ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1517:14)

This time it is complaining that in jest.setup.js file above I used import. The fix for this was quite easy, I rename both jest files to .ts ( jest.setup.jsjest.setup.ts and jest.config.jsjest.config.ts).