-
-
Notifications
You must be signed in to change notification settings - Fork 530
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
Undici 6.x - Request/Response/TextEncoder is not defined (Jest) no longer works #1916
Comments
I had the same issue, but I've solved it with install web-streams-polyfill and modify jest.polyfills.js as bellow:
|
A polyfill of a polyfill? 😄 I hope there is clear solution. |
I know this solution was frowned upon; but it's been working well for me so far, and it does not require Undici. |
@azangru Thanks for the suggestion. I like it better than installing Undici and dealing with incompatibilities with each new version. This is my const JSDOMEnvironment = require("jest-environment-jsdom").default; // or import JSDOMEnvironment from 'jest-environment-jsdom' if you are using ESM modules
class JSDOMEnvironmentExtended extends JSDOMEnvironment {
constructor(...args) {
super(...args);
this.global.ReadableStream = ReadableStream;
this.global.TextDecoder = TextDecoder;
this.global.TextEncoder = TextEncoder;
this.global.Blob = Blob;
this.global.File = File;
this.global.Headers = Headers;
this.global.FormData = FormData;
this.global.Request = Request;
this.global.Response = Response;
this.global.Request = Request;
this.global.Response = Response;
this.global.fetch = fetch;
this.global.structuredClone = structuredClone;
}
}
module.exports = JSDOMEnvironmentExtended; And then in the
|
I've gotten to the point where I don't personally think it's worth it to migrate to v2 if you're using Jest. Part of the amazing thing about this library on v1 is that it just worked. It was a magical DX when you compared it to the alternatives. But now, I'm highly advising anyone using Jest (which many of us are) to just continue using v1. I've followed the official migration docs with various levels of success but never able to reproduce the just works factor. The library authors have taken a pretty clear stance that they consider Jest antiquated even though it's currently 20x more popular than vitest according to npm downloads. And for the record, I do respect their right to take the library in that direction as the maintainers. |
I just want to chime in that the proposed solution using I had to modify the solution as such: const JSDOMEnvironment = require('jest-environment-jsdom').default;
class MyJSDOMEnvironment extends JSDOMEnvironment {
constructor(...args) {
super(...args);
this.global.Request = Request;
this.global.Response = Response;
this.global.TextEncoder = TextEncoder; // Had to add this
this.global.TextDecoder = TextDecoder; // Had to add this
this.global.fetch = fetch;
this.global.structuredClone = structuredClone;
}
}
module.exports = MyJSDOMEnvironment; Even though my tests did pass, I got a billion of these messages in my console:
As such, I'm gonna stick with using the previous major version of |
i tried import this to setupTests.js and still doesnt work |
|
I solve it this way // jest.polyfills.js
const { TextDecoder, TextEncoder, ReadableStream } = require('node:util');
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 },
}); |
this is a test environment configuration, importing that in setup tests won't do anything, so i think that's expected. the test environment solution seems reasonable enough to use though |
- Add msw as a test dependency. Use v1 since v2 has jsdom issues (see mswjs/msw#1916 and jsdom/jsdom#2524) - Resolve fetch polyfill for the test environment
- Add msw as a test dependency. Use v1 since v2 has jsdom issues (see mswjs/msw#1916 and jsdom/jsdom#2524) - Resolve fetch polyfill for the test environment
ConclusionYou are experiencing issues because Jest+JSDOM take away Node.js globals from you (the SolutionThere is nothing we can or should do to fix legacy tooling that doesn't embrace the platform. The issue here isn't caused by MSW, so it's not MSW that should be fixing it. I suggest you migrate to a modern test framework, like Vitest. You are also welcome to tackle this in whichever fashion you choose, using custom Jest environment, downgrading to |
This is the classic answer: "It’s working on my machine". 😄 |
@joel-daros, I cannot fix issues in others' tools. You are encouraged to report this to Jest and JSDOM and to have them address this. You cannot bring a tool that depends on JavaScript into another tool that throws JavaScript out of the window and expect things to work. |
@joel-daros solution works when I combine it with some information from another issue thread. When I add his File: /** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
verbose: true,
preset: 'ts-jest',
testEnvironment: "<rootDir>/jsdom-extended.js",
// Next Line(s) is important! https://github.com/mswjs/msw/issues/1786#issuecomment-1782559851
testEnvironmentOptions: {
customExportConditions: [''],
}, File: const JSDOMEnvironment = require("jest-environment-jsdom").default; // or import JSDOMEnvironment from 'jest-environment-jsdom' if you are using ESM modules
class JSDOMEnvironmentExtended extends JSDOMEnvironment {
constructor(...args) {
super(...args);
this.global.ReadableStream = ReadableStream;
this.global.TextDecoder = TextDecoder;
this.global.TextEncoder = TextEncoder;
this.global.Blob = Blob;
this.global.File = File;
this.global.Headers = Headers;
this.global.FormData = FormData;
this.global.Request = Request;
this.global.Response = Response;
this.global.Request = Request;
this.global.Response = Response;
this.global.fetch = fetch;
this.global.structuredClone = structuredClone;
}
}
module.exports = JSDOMEnvironmentExtended; I have written an article on medium about it ⇾ Jest + React + MSW + Webpack — Solution for Errors |
@tobiashochguertel, thanks for putting the custom environment up! So, because in the environment class' context we're still in regular Node.js, we can grab the globals without having to explicitly import them from anywhere? This is interesting. Sounds like it solves the My only concern with this is that it's a workaround. I feel uncomfortable recommending workarounds. Granted, what we recommend in the docs right now is also a workaround, albeit with a bit smaller effect area. I'd much prefer to see those changes you propose to be a part of Did you consider raising this as an issue/pull request to Jest? That would be a nice solution for everyone (and a contribution opportunity for you too!). |
Yes, it solved the problem with the
@kettanaito I didn't think on that. I don't understand the solution completely, I just was good at puzzling everything together. I didn't want to migrate to Vite now. |
Just wanted to add here that I'm on node 18, and I had to remove the |
I tried the |
It would be nice if docs can reflect this in FAQ https://mswjs.io/docs/faq#requestresponsetextencoder-is-not-defined-jest rather than suggesting only one options of jest polyfills |
UpdateThank you so much everyone for battling your way through this. I think we should publish that custom Jest environment to NPM and recommend it officially for everyone using MSW (and beyond, really). I've created the Thanks. |
Hi @kettanaito, just wanted to say that as a spectator of this issue for some time, we appreciate your time and effort spent on solving this problem, even though it's not an issue caused by msw. I've enjoyed removing my polyfills and undici. Thank you. |
Thank you for the great effort and time @kettanaito 🚀 |
@robbieaverill @piyushchauhan2011 means a lot to me to hear this. I know issues like this suck. I also understand how natural it is to blame the tool that seemingly causes the issue when, in fact, it just helps it surface. I hope |
😃 Me too. But what does the landscape of test runners currently look like? Last time I checked, there was Web Test Runner, by the Modern Web project; but I think it is targeting primarily browser-native code, which something like React is not. And there was also Playwright component testing, but it has remained experimental for over a year, and is emphatically not a priority for the Playwright team. Have there been any developments among test runners that give you hope that we can move to testing our UI components, which at this point are predominantly React, in the browser? |
@azangru, there's a Browser mode in Vitest, which looks promising. What Playwright is doing with component-level testing for React is also good and I hope it finds the proper love it needs from the team. In the RSC era, unless the frameworks expose the rendering/hydration pipelines, there will be no reliable way to test RSC on an integration level. That's concerning. I really hope the frameworks will work on this. |
Importing // jest.polyfills.js
const { TextDecoder, TextEncoder } = require('node:util');
const { ReadableStream } = require('node:stream/web'); // <--- this did the magic
Object.defineProperties(globalThis, {
TextDecoder: { value: TextDecoder },
TextEncoder: { value: TextEncoder },
ReadableStream: { value: ReadableStream },
});
const { Blob, File } = require('node:buffer');
const { fetch, Response, Request, FormData, Headers } = 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 },
}); |
Please note that the recommended way forward is to use the https://github.com/mswjs/jest-fixed-jsdom package in Jest. Then you don't have to create the setup file at all. It also correctly remaps the globals on the test environment level, where you don't have to import them from |
This worked for me. I'm using vitest with jsdom so it seems this issue is not only related to jest. |
Prerequisites
Environment check
msw
versionNode.js version
v18.19.0
Reproduction repository
http://
Reproduction steps
Current behavior
The documentation suggestion to create a
jest.polyfills.js
no longer works in Undici version 6.xAll tests are returning the same error:
Expected behavior
An update version of
jest.polyfills.js
The text was updated successfully, but these errors were encountered: