Reputation: 204
I have a working react app, where I use msw
for mocking BE in browser and in tests (Jest).
With msw v1.3.0 everything works perfectly fine, I've decided to update it v2.0 and there I've encountered problems. All my tests fail because of the error ReferenceError: TextEncoder is not defined
. In browser mode it works fine though.
I've contacted msw
support and they told me this issue is Jest related. I've tried many workarounds how to define TextEncoder
in usual cases where that might work, but all in vain.
p.s. all versions are new (node: v18.14.2, npm: v9.5.0, typescript: v4.9.5, react: v18.2.0, jest: v27.5.1). And I run my tests with craco test
I've tried to create a separate jest.config.js
file and define TextEncoder
like this:
module.exports = {
globals: {
TextEncoder: require('util').TextEncoder,
TextDecoder: require('util').TextDecoder,
}
}
and from the file:
module.exports = {
setupFiles: ['<rootDir>/setupFiles.js'],
}
I've tried to import TextEncoder from 'util' and 'node:util':
const { TextDecoder, TextEncoder } = require('node:util');
Object.defineProperties(globalThis, {
TextDecoder: { value: TextDecoder, writable: true },
TextEncoder: { value: TextEncoder, writable: true },
});
I've tried to import it from the different external 'text-encoding' libraries.
And add testEnvironment: 'node'
in configs.
But all of that doesn't work for my case.
Upvotes: 17
Views: 20386
Reputation: 31
In my case I work with react-vite and the error was
Test suite failed to run
ReferenceError: TextEncoder is not defined
but all I do to fix it was update the jest.setup.js with this
import { TextDecoder, TextEncoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
Upvotes: 2
Reputation: 6581
My suspicion is that these "environment" libraries use VM another library internally to create a sandbox. Both JSDOM and it's competitor HappyDOM don't have an implementation for TextDecoder / TextEncoder present on their globals and therefore not only are they not found, but you can't add them without access to their global context inside the VM.
The reason they do this is they emulate the browser, and it wouldn't make sense if for example 'fs' or other node standard libraries to be accessible.
Try this and let me know if it works; Works for me on Node 18.18.2 with MSW 2.0
// inside your jest.setup.js
testEnvironment: "./jest.environment.js",
// jest.environment.js
const Environment = require("jest-environment-jsdom").default;
module.exports = class CustomTestEnvironment extends Environment {
async setup() {
await super.setup();
this.global.TextEncoder = TextEncoder;
this.global.TextDecoder = TextDecoder;
this.global.Response = Response;
this.global.Request = Request;
}
};
I would consider this solution a partial hack, but your options are pretty limited outside of creating a PR or issue with JSDOM or HappyDOM to add support for these.
Upvotes: 8
Reputation: 1590
This has now been updated in the documentation of MSW:
https://mswjs.io/docs/migrations/1.x-to-2.x/#requestresponsetextencoder-is-not-defined-jest
But ensure that you use undici
v5 in your package.json.
Upvotes: 1
Reputation: 101
This work for me
//setup.jest.js
import { TextDecoder, TextEncoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
Then calling within jest.config.js file with attr -> "setupFiles"
module.exports = {
// preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFiles: ['<rootDir>/setup.jest.js'],
globals: {
Uint8Array: Uint8Array,
},
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
transform: {
'^.+.[tj]sx?$': [
'babel-jest',
],
},
};
Upvotes: 9