msw-storybook-addon
msw-storybook-addon copied to clipboard
Using the addon v2 with Jest
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?
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)
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.
// 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.
I have the same issue with the following error.
Invariant Violation: [MSW] Failed to execute
setupWorker
in a non-browser environment. Consider usingsetupServer
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.
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
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 I have onUnhandledRequest
configured to bypass unhandled requests
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! 👍
but I have another issues now. looks like response is not returned from my mocked request.
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.
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.
Re-adding mswDecorator fixed for me.
// preview.ts
import { initialize, mswDecorator, mswLoader } from 'msw-storybook-addon';
export const decorators: Decorator[] = [
mswDecorator,
...
]
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? :)
:rocket: Issue was released in v2.0.1
:rocket:
Hey @dmitriy-kudelko @alextrukhan @kodai3 @SamSverko could you please try 2.0.1 out and let me know if all goes well?
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.
@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.
@yannbf , same here. I also don't see any improvement in the behavior in this regard.
Could any of you please provide a minimal reproduction so I can take a better look? Thank you!