Skip to content
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

jest jsdom: ReferenceError: TextEncoder is not defined #1676

Closed
1 of 5 tasks
angelo-v opened this issue Sep 10, 2021 · 22 comments
Closed
1 of 5 tasks

jest jsdom: ReferenceError: TextEncoder is not defined #1676

angelo-v opened this issue Sep 10, 2021 · 22 comments
Labels
bug Something isn't working

Comments

@angelo-v
Copy link

Search terms you've used

jsdom, TextEncoder

Impacted package

Which packages do you think might be impacted by the bug ?

  • solid-client-authn-browser
  • solid-client-authn-node
  • solid-client-authn-core
  • oidc-client-ext
  • Other (please specify): ...

Bug description

importing from @inrupt/solid-client-authn-browser fails in a jest test using jsdom environment:

Test suite failed to run

    ReferenceError: TextEncoder is not defined

      3 |  */
      4 |
    > 5 | import { login } from '@inrupt/solid-client-authn-browser';
        | ^
      6 |
      7 | describe('test', () => {
      8 |   it('should work', () => {

To Reproduce

Run this test:

/**
 * @jest-environment jsdom
 */

import { login } from '@inrupt/solid-client-authn-browser';

describe('test', () => {
  it('should work', () => {
    expect(login).toBeDefined();
  });
});

Expected result

Test runs successfully

Actual result

ReferenceError: TextEncoder is not defined

Environment

 @inrupt/solid-client-authn-browser: ^1.11.2 => 1.11.2

Additional information

  • The problem did not occur with @inrupt/solid-client-authn-browser 1.6.1
  • It works fine with @jest-environment node
@angelo-v angelo-v added the bug Something isn't working label Sep 10, 2021
@angelo-v
Copy link
Author

A workarround (or solution?) is to polyfill TextEncoder and TextDecoder in a setupFilesAfterEnv script:

import { TextEncoder, TextDecoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

@NSeydoux
Copy link
Contributor

Hi @angelo-v ! I think this issue unfortunately goes beyond the scope of @inrupt/solid-client-authn-browser, and we have to work around it ourselves: jose expects TextEncoder to be present in the environment, but jsdom does not put it there (see jsdom/jsdom#2524). Our solution (suggested somewhere in the linked issue) is to use a custom Jest environment: https://github.com/inrupt/solid-client-authn-js/blob/main/tests/environment/customEnvironment.js, referenced e.g. in https://github.com/inrupt/solid-client-authn-js/blob/main/packages/browser/jest.config.js.

@angelo-v
Copy link
Author

Thanks, I understand that. Using setupFilesAfterEnv works as well and is more lightweight then creating a custom jest env imo. Perhaps you can at least add a hint to the documentation about that, because usually people just using the inrupt lib do not know about jose and those internals, they just wonder why the inrupt lib causes an error in the tests

@CalebJamesStevens
Copy link

Still an issue today. Jest 29, added the util script

@JaldinDeveloper
Copy link

just import it with require
const { JSDOM } = require("jsdom");
I got the same issue and this solution worked for me

@hjohnsick
Copy link

hjohnsick commented Oct 12, 2022

A workarround (or solution?) is to polyfill TextEncoder and TextDecoder in a setupFilesAfterEnv script:

import { TextEncoder, TextDecoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

How exactly do I add this to a setupFilesAfterEnv script? I am using typescript and I have a jest-config.d.ts and it has this inside,

declare const root: any;
export { root as rootDir };
export declare const setupFilesAfterEnv: string[];
export declare const testMatch: string[];
export declare const testPathIgnorePatterns: string[];
export declare const coveragePathIgnorePatterns: string[];
export declare const coverageDirectory: string;

@ThisIsMissEm
Copy link
Contributor

We actually have a bit of an update here: we've just released a package that helps by polyfilling the required Web APIs: https://www.npmjs.com/package/@inrupt/jest-jsdom-polyfills

It's still being rolled out across the SDK repos, but in our testing so far it should provide everything needed. We're aware that there may be an issue with UInt8Arrays, and that's due to an underlying jsdom issue: jsdom/whatwg-encoding#13

@ThisIsMissEm
Copy link
Contributor

@hjohnsick you can see an example here: https://github.com/inrupt/solid-client-access-grants-js/pull/366/files

You should likely have a jest.config.ts file in your repo, unless you're somehow using jest without any configuration at all (which I've only rarely seen)

@ThisIsMissEm
Copy link
Contributor

ThisIsMissEm commented Oct 14, 2022

Thanks, I understand that. Using setupFilesAfterEnv works as well and is more lightweight then creating a custom jest env imo. Perhaps you can at least add a hint to the documentation about that, because usually people just using the inrupt lib do not know about jose and those internals, they just wonder why the inrupt lib causes an error in the tests

@angelo-v Yup, we agree, we've since moved from custom environments to setupFilesAfterEnv

@allestaire
Copy link

Seems like the answers didnt state where to put the said code.

@NSeydoux
Copy link
Contributor

You can use this repository as an example: see https://github.com/inrupt/solid-client-authn-js/blob/main/jest.setup.ts, where the polyfills are imported, and

setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
, where jest is configured to pick up this setup.

@clarkeustaquio
Copy link

Only solution worked to me is to add this line of code to src/setupTests.ts

import '@testing-library/jest-dom';
import { TextEncoder } from 'util';

global.TextEncoder = TextEncoder;

@ThisIsMissEm
Copy link
Contributor

Only solution worked to me is to add this line of code to src/setupTests.ts

import '@testing-library/jest-dom';
import { TextEncoder } from 'util';

global.TextEncoder = TextEncoder;

It's strange you needed that as we do that polyfill of textencoder in our polyfill.. I can't comment on testing lib & jest-dom though. If you've a repo to share I'd love to run a few experiments to check our package is working as expected

@danielbakas
Copy link

Problem still present. Adding this to setupTests.js still works:

import { TextEncoder } from 'util';

global.TextEncoder = TextEncoder;

@jeswr
Copy link
Contributor

jeswr commented Jul 3, 2023

Closing this issue as it is an error in Jest with a workaround (i.e. #1676 (comment))

@vojdan
Copy link

vojdan commented Jan 4, 2024

Only solution worked to me is to add this line of code to src/setupTests.ts

import '@testing-library/jest-dom';
import { TextEncoder } from 'util';

global.TextEncoder = TextEncoder;

This worked for me when using CRA.

@kokombo
Copy link

kokombo commented Jan 9, 2024

This did not work for me. Still getting '
ReferenceError: TextEncoder is not defined'

@Alfredoeb9
Copy link

Alfredoeb9 commented Jan 25, 2024

Solution above did not work for me either, after some trail and error found this to work for me:

// inside your env.setup.js
testEnvironment: "<rootDir>/test/test-config/env-setup.js",

// env-setup.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;
        
    }
};

@NSeydoux
Copy link
Contributor

@BowaDAO can you describe your setup a bit more so that I would be able to help?

@Alfredoeb9 thanks for providing something that works around the issue in your case. Can you elaborate a bit more on your setup as well, so that I may figure out why the solution we use for ourselves now doesn't cover your use case?

@kokombo
Copy link

kokombo commented Feb 28, 2024

I've been able to resolve the issue.

@christopher-theagen
Copy link

.jest/setup.js

import { TextEncoder, TextDecoder } from 'util';

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

@Milan-960
Copy link

I am also having the same issue and it does not help me to resolve that. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests