Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the addon v2 with Jest #145

Closed
dmitriy-kudelko opened this issue Apr 18, 2024 · 18 comments · Fixed by #152
Closed

Using the addon v2 with Jest #145

dmitriy-kudelko opened this issue Apr 18, 2024 · 18 comments · Fixed by #152
Assignees
Labels
released This issue/pull request has been released.

Comments

@dmitriy-kudelko
Copy link

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?

@SamSverko
Copy link

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)

@kodai3
Copy link

kodai3 commented Apr 23, 2024

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
Copy link

kodai3 commented Apr 23, 2024

// 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.

@alextrukhan
Copy link

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
Copy link

alextrukhan commented Apr 23, 2024

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

@kodai3
Copy link

kodai3 commented Apr 23, 2024

@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 }) => { ... 

@alextrukhan
Copy link

@kodai3 I have onUnhandledRequest configured to bypass unhandled requests

@dmitriy-kudelko
Copy link
Author

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! 👍

@alextrukhan
Copy link

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

@kodai3
Copy link

kodai3 commented Apr 23, 2024

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.

@dmitriy-kudelko
Copy link
Author

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.

@kodai3
Copy link

kodai3 commented Apr 23, 2024

Re-adding mswDecorator fixed for me.

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

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

@alextrukhan
Copy link

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? :)

Copy link

github-actions bot commented May 3, 2024

🚀 Issue was released in v2.0.1 🚀

@github-actions github-actions bot added the released This issue/pull request has been released. label May 3, 2024
@yannbf
Copy link
Collaborator

yannbf commented May 3, 2024

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

@kodai3
Copy link

kodai3 commented May 3, 2024

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.

@alextrukhan
Copy link

@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.

@dmitriy-kudelko
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released This issue/pull request has been released.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants