msw-storybook-addon icon indicating copy to clipboard operation
msw-storybook-addon copied to clipboard

Using the addon v2 with Jest

Open dmitriy-kudelko opened this issue 10 months ago • 13 comments

Hello,

I spent some time migrating from v1 (both msw and the addon) to v2. And it almost worked except for tests (Jest).

A first problem was that the module needed to be tranformed, otherwise throwing:

import { setupWorker } from "msw/browser";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

So I had to add msw-storybook-addon to jest config transformIgnorePatterns so that it's transformed.

Then I got:

 ReferenceError: TextEncoder is not defined

So I found that in this case we need to add some polyfills, which I did: https://mswjs.io/docs/migrations/1.x-to-2.x/#requestresponsetextencoder-is-not-defined-jest

However after doing this Jest throws another error:

Invariant Violation: [MSW] Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for Node.js environment instead.

Is there a recommended way to make it work with Jest?

dmitriy-kudelko avatar Apr 18 '24 14:04 dmitriy-kudelko

I'm in the exact same boat! Unfortunately, nothing has worked for me either.

What I'm getting:

demo-repo-folder/node_modules/msw-storybook-addon/dist/index.browser.js:2
    import { setupWorker } from "msw/browser";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import { initialize, mswLoader } from 'msw-storybook-addon'
        | ^
      2 |
      3 | initialize({ onUnhandledRequest: 'bypass' })
      4 |

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)
      at Object.require (.storybook/baseLoaders.tsx:1:1)
      at Object.require (.storybook/testConfig.ts:2:1)
      at Object.require (src/components/DemoComponent/__tests__/DemoComponent.test.tsx:6:1)

SamSverko avatar Apr 22 '24 19:04 SamSverko

Same issue here. Because I use next/jest and it has default configuration here, I had to setup transpilePackages in next.config.js instead of setting transformIgnorePatterns for nextJest function in jext.config.js

Then, Getting stuck with the same error

Invariant Violation: [MSW] Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for Node.js environment instead.

kodai3 avatar Apr 23 '24 04:04 kodai3

// preview.ts
let initialize;
let mswLoader;
if (process.env.NODE_ENV === 'test') {
  const node = require('../node_modules/msw-storybook-addon/dist/index.node');
  initialize = node.initialize;
  mswLoader = node.mswLoader;
} else {
  const browser = require('../node_modules/msw-storybook-addon/dist/index.browser');
  initialize = browser.initialize;
  mswLoader = browser.mswLoader;
}

Doing like this will run both storybook and jest.

But still throw another error regarding msw mock

TypeError: Failed to fetch
          at createNetworkError (/.../app/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:206:24)
          at globalThis.fetch (/.../app/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:116:31) {
        cause: Error: Please mock any requests to gateway with msw.

kodai3 avatar Apr 23 '24 05:04 kodai3

I have the same issue with the following error.

Invariant Violation: [MSW] Failed to execute setupWorker in a non-browser environment. Consider using setupServer for Node.js environment instead.

looks like the issue is with use of "jsdom" testing environment together with initialize from addon. when testing environment not specified, jest select correct version of initialize function(one for node), but test fail due to incorrect env. if jsdom specified, initialize for browser env is selected and test fails.

alextrukhan avatar Apr 23 '24 11:04 alextrukhan

after doing everything that @dmitriy-kudelko mentioned in the description and

https://jestjs.io/docs/configuration#testenvironmentoptions-object after adding the following to my jest config that is used to run storybook based tests, everything work correctly

  testEnvironmentOptions: {
    customExportConditions: ["node", "node-addons"],
  },

basically this does the same that @kodai3 did in his last answer but via jest

alextrukhan avatar Apr 23 '24 12:04 alextrukhan

@alextrukhan

Thanks, it indeed replaces my code for me as well

The error I get after adding those workaround.

TypeError: Failed to fetch
          at createNetworkError (/.../app/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:206:24)
          at globalThis.fetch (/.../app/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:116:31) {
        cause: Error: Please mock any requests to gateway with msw.

it seems to be caused by onUnhandledRequest so it might be different issue. (the error won't come up if i delete onUnhandledRequest)

initialize({
  onUnhandledRequest: ({ url }) => { ... 

kodai3 avatar Apr 23 '24 13:04 kodai3

@kodai3 I have onUnhandledRequest configured to bypass unhandled requests

alextrukhan avatar Apr 23 '24 13:04 alextrukhan

after doing everything that @dmitriy-kudelko mentioned in the description and

https://jestjs.io/docs/configuration#testenvironmentoptions-object after adding the following to my jest config that is used to run storybook based tests, everything work correctly

  testEnvironmentOptions: {
    customExportConditions: ["node", "node-addons"],
  },

basically this does the same that @kodai3 did in his last answer but via jest

I confirm. This worked for me as well. Thanks for the update! 👍

dmitriy-kudelko avatar Apr 23 '24 13:04 dmitriy-kudelko

but I have another issues now. looks like response is not returned from my mocked request.

alextrukhan avatar Apr 23 '24 13:04 alextrukhan

The queries (gql queries and mutations for may usecase) I mocked via storybook's parameters.msw.handlers are unhandled and going to onUnhandledRequest without returning expected values

and that was the cause the error I mentioned above through our validation.

kodai3 avatar Apr 23 '24 13:04 kodai3

but I have another issues now. looks like response is not returned from my mocked request.

Yeah.. same here. I only checked that Jest just runs at first without executing any test which actually relies on MSW.

dmitriy-kudelko avatar Apr 23 '24 13:04 dmitriy-kudelko

Re-adding mswDecorator fixed for me.

// preview.ts
import { initialize, mswDecorator, mswLoader } from 'msw-storybook-addon';

export const decorators: Decorator[] = [
  mswDecorator,
  ...
]

kodai3 avatar Apr 23 '24 14:04 kodai3

also had error inside HttpResponse.json() in my msw handlers. the following jest.polyfills.js helped.

added: const { ReadableStream } = require("node:stream/web"); and ReadableStream: { value: ReadableStream },

// jest.polyfills.js
/**
 * @note The block below contains polyfills for Node.js globals
 * required for Jest to function when running JSDOM tests.
 * These HAVE to be require's and HAVE to be in this exact
 * order, since "undici" depends on the "TextEncoder" global API.
 *
 * Consider migrating to a more modern test runner if
 * you don't want to deal with this.
 */

const { TextDecoder, TextEncoder } = require("node:util");
const { ReadableStream } = require("node:stream/web");

Object.defineProperties(globalThis, {
  TextDecoder: { value: TextDecoder },
  TextEncoder: { value: TextEncoder },
  ReadableStream: { value: ReadableStream },
});

const { Blob, File } = require("node:buffer");
const { fetch, Headers, FormData, Request, Response } = require("undici");

Object.defineProperties(globalThis, {
  fetch: { value: fetch, writable: true },
  Blob: { value: Blob },
  File: { value: File },
  Headers: { value: Headers },
  FormData: { value: FormData },
  Request: { value: Request },
  Response: { value: Response },
});

also it worked for me without adding mswDecorator. could somebody try to get rid of decorator and change polyffils to one provided above? :)

alextrukhan avatar Apr 24 '24 07:04 alextrukhan

:rocket: Issue was released in v2.0.1 :rocket:

github-actions[bot] avatar May 03 '24 16:05 github-actions[bot]

Hey @dmitriy-kudelko @alextrukhan @kodai3 @SamSverko could you please try 2.0.1 out and let me know if all goes well?

yannbf avatar May 03 '24 16:05 yannbf

It seems v2.0.1 doesn't change and still throws Invariant Violation: [MSW] Failed to execute setupWorker in a non-browser environment. Consider using setupServer for Node.js environment instead. error for me.

kodai3 avatar May 03 '24 17:05 kodai3

@yannbf after update to v2.0.2 and removal of the following code from config

  testEnvironmentOptions: {
    customExportConditions: ["node", "node-addons"],
  },

I still get the following error: Invariant Violation: [MSW] Failed to execute setupWorker in a non-browser environment. Consider using setupServer for Node.js environment instead.

alextrukhan avatar May 09 '24 09:05 alextrukhan

@yannbf , same here. I also don't see any improvement in the behavior in this regard.

dmitriy-kudelko avatar May 09 '24 10:05 dmitriy-kudelko

Could any of you please provide a minimal reproduction so I can take a better look? Thank you!

yannbf avatar May 16 '24 12:05 yannbf