53

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?

4 Answers 4

113

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.

3
  • 6
    Where should this be added? I added it to the file that housing my failing test I get this error under global.TextDecoder Type 'typeof TextDecoder' is not assignable to type '{ new (label?: string | undefined, options?: TextDecoderOptions | undefined): TextDecoder; prototype: TextDecoder; }' Commented Aug 5, 2022 at 15:20
  • 2
    @dragonfly02 You will have to add that to the test or to a setupFile
    – leonheess
    Commented Aug 23, 2022 at 9:33
  • In my case, I had to do: ``` import { TextDecoder as ImportedTextDecoder, TextEncoder as ImportedTextEncoder, } from "util"; Object.assign(global, { TextDecoder: ImportedTextDecoder, TextEncoder: ImportedTextEncoder, }); ``` Commented Mar 7 at 8:52
36

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

4
  • 1
    Note that in the specific case where this is caused by indirectly by 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: () => ({}), }) ); Commented Jan 13, 2023 at 2:54
  • 1
    This saved my bacon today, decided to mark my whole library as a node env testEnvironment: 'node',. Commented Jun 5, 2023 at 5:42
  • 1
    This doesn't work if you need to say access the 'window' object in your test file. Commented Jul 10, 2023 at 15:08
  • @scottseeker I believe you need to mock the window object for that. Here's a question/answer combo with solutions for that: stackoverflow.com/questions/41885841/… Commented Jul 10, 2023 at 15:50
4

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.

-8

Make sure your whatwg-url package has version ^10.0.0 at least

Not the answer you're looking for? Browse other questions tagged or ask your own question.