When testing a function that uses either the TextEncoder or the TextDecoder I get:
ReferenceError: TextEncoder is not defined
ReferenceError: TextDecoder is not defined
I am using jsdom, so why is this not working?
When testing a function that uses either the TextEncoder or the TextDecoder I get:
ReferenceError: TextEncoder is not defined
ReferenceError: TextDecoder is not defined
I am using jsdom, so why is this not working?
While it should be bundled with jsdom, it isn't with jsdom 16. Therefore you can polyfill like so:
import { TextEncoder, TextDecoder } from 'util';
Object.assign(global, { TextDecoder, TextEncoder });
You will have to add that to the test or to a setupFile like setup.jest.ts.
TypeError: Cannot assign to read only property 'TextDecoder' of object '[object global]'I received this error as well and am using the standard Next.js jest and react testing library test setup outlined in the docs here: https://nextjs.org/docs/testing#setting-up-jest-with-the-rust-compiler.
In particular, it uses the testEnvironment: 'jest-environment-jsdom'
test environment in jest.config.js configuration file.
Unfortunately, importing jsdom in one of my backend api routes (Express routes) broke my tests, giving me the TextEncoder is not defined error.
I was able to fix it by adding the following to the top of the file that housed the broken test:
/**
* @jest-environment node
*/
// my-broken-node-only-test.js
Read more about this technique via the jest docs.
Lastly, the following issue comment by Jest maintainer Simen helped clarify what was happening in my case: https://github.com/jsdom/jsdom/issues/2524#issuecomment-902027138
isomorphic-fetch (which in turn needs whatwg-url) you can probably get away with just mocking isomorphic-fetch: js jest.mock('isomorphic-fetch', () => () => Promise.resolve({ json: () => ({}), }) ); testEnvironment: 'node',.window object for that. Here's a question/answer combo with solutions for that: stackoverflow.com/questions/41885841/…To add to @leonheess's answer in TypeScript:
Add to the top of your testfile (in which the error occurs, before the line that causes the error):
import { TextEncoder, TextDecoder } from 'util'
global.TextEncoder = TextEncoder
// @ts-expect-error
global.TextDecoder = TextDecoder
Even when trying nicely, e.g.
import { TextEncoder, TextDecoder } from 'util'
global.TextEncoder = TextEncoder
global.TextDecoder = { prototype: TextDecoder }
I got errors like
Type 'typeof TextDecoder' is missing the following properties from type 'TextDecoder': decode, encoding, fatal, ignoreBOMts(2739)
Or with
global.TextDecoder = {prototype: new TextDecoder("utf-8")}
I get
Type 'import("util").TextDecoder' is not assignable to type 'TextDecoder'.
Types of property 'decode' are incompatible.
Type '(input?: ArrayBuffer | ArrayBufferView | null | undefined, options?: { stream?: boolean | undefined; } | undefined) => string' is not assignable to type '(input?: BufferSource | undefined, options?: TextDecodeOptions | undefined) => string'.
Types of parameters 'input' and 'input' are incompatible.
Type 'BufferSource | undefined' is not assignable to type 'ArrayBuffer | ArrayBufferView | null | undefined'.
Type 'ArrayBufferView' is not assignable to type 'ArrayBuffer | ArrayBufferView | null | undefined'.
Type 'ArrayBufferView' is missing the following properties from type 'DataView': getFloat32, getFloat64, getInt8, getInt16, and 17 more.
So better to just assign and ignore the incompatibilities.
import { TextEncoder, TextDecoder } from 'util'
global.TextEncoder = TextEncoder
// @ts-expect-error
global.TextDecoder = TextDecoder
EDIT: I know this is ugly, but found no other way.
There is a package that fixes this for anyone having this issue.
npm install jest-fixed-jsdom --save-dev
yarn add jest-fixed-jsdom --dev
Then in your jest.config.js|ts file you add this config below likely replacing jsdom
module.exports = {
testEnvironment: 'jest-fixed-jsdom',
}
There some more information about this here Request/Response/TextEncoder is not defined (Jest)
@jest-environment jsdom), it will override the testEnvironment specified in config and it won't take effect, so make sure you remove that.Fix for ReferenceError: TextEncoder is not defined with Cheerio and Jest
If you're seeing this error when running Jest tests:
ReferenceError: TextEncoder is not defined
With a stack trace like:
at Object.<anonymous> (node_modules/undici/lib/web/fetch/data-url.js:5:17)
...
at Object.<anonymous> (node_modules/cheerio/...)
The issue is caused by newer versions of cheerio (v2+) which use undici under the hood. undici depends on TextEncoder, which isn't available in Jest's Node environment by default.
Install a version of Cheerio that doesn't rely on undici:
npm install [email protected]
This version avoids the TextEncoder issue and works properly with Jest without needing polyfills or Node 18+.
jest.setup.ts
import { TextEncoder, TextDecoder } from 'util';
// Polyfill for TextEncoder
if (typeof global.TextEncoder === 'undefined') {
global.TextEncoder = TextEncoder;
}
if (typeof window.TextEncoder === 'undefined') {
window.TextEncoder = global.TextEncoder;
}
// Polyfill for TextDecoder
if (typeof global.TextDecoder === 'undefined') {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
global.TextDecoder = TextDecoder;
}
if (typeof window.TextDecoder === 'undefined') {
window.TextDecoder = global.TextDecoder;
}
console.log('Polyfill for TextEncoder/TextDecoder loaded.');
jest.config.ts Add the following property in the config object:
setupFiles: ['<rootDir>/jest.setup.ts']
I fixed this issue by using 'jest-fixed-jsdom' environment instead of 'jest-environment-jsdom'. This commonly happens when using 'jest-environment-jsdom' because it intentionally replaces built-in APIs with polyfills, breaking their Node.js compatibility.
You can solve this by doing the following: Terminal:
npm i -D jest-fixed-jsdom
Replacing code in your Jest config file (jest.config.js) from
module.exports = config;
to:
module.exports = { testEnvironment: 'jest-fixed-jsdom' }
Reference: https://mswjs.io/docs/faq/#requestresponsetextencoder-is-not-defined-jest
When using testEnvironment: 'jsdom', Jest uses the JSDOM environment, which doesn't inherit Node’s globals like TextEncoder by default.
So even in Node 18 or 20, you still need to manually inject TextEncoder into the global scope if JSDOM is your test environment.
Replace the code in jest.config.js with the below code:
// jest.config.js
const { TextEncoder, TextDecoder } = require('util');
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
const config = {
clearMocks: true,
collectCoverage: true,
coverageDirectory: "coverage",
testEnvironment: "jsdom",
setupFilesAfterEnv: ['<rootDir>/jest.config.js'],
//path to config file
};
module.exports = config;
That's it. I hope it solves your problem. Happy testing.
in case anyone using enzyme and gets this error, lock cheerio dependancy to 1.0.0-rc.12 version in your package.json and re-install deps.
rc versions of cheerio is the latest compatible with enzyme.
What I found in my node_modules is that enzyme had cheerio at ^1.0.0-rc.3 but ^ allowed your pckg manager to pull and install v1 breaking stuff.
I was getting this error while running tests. There was a parent package which is used in my code, inside this parent package, it is referring to the TextDecoder.
So I have mocked the parent package to get it working.
jest.mock('parent-package', () => ({
<nameOfModudeImported>: jest.fn(() => ({
<nameOfMethodCalled>: jest.fn(() =>
// the above method returns a promise, so mock how your component behaves.
Promise.resolve({
body: {
result: {
url: 'mocked-url',
},
},
}),
),
})),
}));