Skip to content

TypeError: MutationObserver is not a constructor #731

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

Closed
KevinBurton opened this issue Jul 4, 2020 · 24 comments
Closed

TypeError: MutationObserver is not a constructor #731

KevinBurton opened this issue Jul 4, 2020 · 24 comments

Comments

@KevinBurton
Copy link

I have a test like

import React from "react";
import { render, screen } from "@testing-library/react";
import Countdown from "./Countdown";
describe('Countdown', () => {
    test("renders Countdown without crashing", async () => {
        const { container, getByText } = render(<Countdown timeTillDate="07 08 2020, 6:00 am" timeFormat="MM DD YYYY, h:mm a" />);
        await screen.findByText('Countdown');
        // render should show the title
        expect(getByText(/Countdown/)).toBeInTheDocument();
        expect(container).toContainElement(document.querySelector('h1'));
    });
});

This test fails with an exception

TypeError: MutationObserver is not a constructor

This same issue was raised and closed because a polyfill solved the problem. But it was also mentioned that with the latest code a polyfill was not needed. The web application that I am using was originally started with Create-React-App. Here is a snippet of my package.json to get an idea of the versions I am using:

    "@testing-library/dom": "^7.20.0",
    "@testing-library/jest-dom": "^5.11.0",
    "@testing-library/react": "^10.4.3",
    "@testing-library/user-event": "^12.0.11",
...
    "cross-env": "6.0.3",
...
    "ts-jest": "^26.1.1",
    "typescript": "3.9.6"

With these versions I shouldn't need a polyfill right?

Thank you.

@tjefferson08
Copy link

Is this the issue you were referring to? #730

For #730, the issue was that two different dependencies both specified different versions of jsdom. It seems like that's a possibilty here as well. If you'd like to troubleshoot this hypothesis, you can poke around your package-lock.json/yarn.lock and try to figure out what versions of jsdom are being specified.

As for polyfilling... 🤔 I suspect your application/dev env is polyfilling MutationObserver appropriately, but it's plausible that polyfilling is not applied in the same way (or at all!) to your test environment. That's another avenue you could explore!

This issue seems pretty common, it might be worth a dedicated spot in the docs (or even a custom error message?)

@nickserv
Copy link
Member

nickserv commented Jul 4, 2020

Also it's easier to check duplicate versions with npm ls jsdom or yarn why jsdom. Make sure you're using the same package manager you install the project with or the result may be incorrect.

@KevinBurton
Copy link
Author

KevinBurton commented Jul 4, 2020 via email

@nickserv
Copy link
Member

nickserv commented Jul 5, 2020

There are three versions of jsdom (starting with => Found), all installed as dependencies within react-scripts. Try upgrading the package.

@KevinBurton
Copy link
Author

KevinBurton commented Jul 5, 2020 via email

@nickserv
Copy link
Member

nickserv commented Jul 5, 2020

You might be able to upgrade the other dependencies with yarn upgrade. If that doesn't work, it would be helpful to have a Code Sandbox of this issue. https://codesandbox.io/s/new

@marcosvega91
Copy link
Member

marcosvega91 commented Jul 5, 2020

Could you please try to update jest-config to @^26.1.0 ?

@KevinBurton
Copy link
Author

I don't see jest-config in in the list of dependencies. Should it be added?

@AndonIgnatov
Copy link

Kevin try this: https://stackoverflow.com/questions/61036156/react-typescript-testing-typeerror-mutationobserver-is-not-a-constructor

@KevinBurton
Copy link
Author

KevinBurton commented Jul 14, 2020 via email

@TijmenH
Copy link

TijmenH commented Jul 15, 2020

temp solution but I've added the MutationObserver package to the devDependencies and adding it to the global scope like this before running tests:

import MutationObserver from "mutation-observer";
global.MutationObserver = MutationObserver;

@nogashimoni
Copy link

nogashimoni commented Aug 2, 2020

For other people facing the "MutationObserver is not a constructor" issue, It took me some time to figure out what's the basic solution, so I'm posting this because it might save you some time.

go to this part in the documentation: https://testing-library.com/docs/react-testing-library/setup#jest-24-or-lower-and-defaults

react-scripts includes a dependency called jest-environment-jsdom-fourteen.

All I had to do to get rid of the MutationObserver problem, is to run the test using a jest option: --env jest-environment-jsdom-fourteen

@rmnbod
Copy link

rmnbod commented Aug 19, 2020

Having the same problem having latest packages installed, none of the solutions seem to work.

@MatanBobi
Copy link
Member

Having the same problem having latest packages installed, none of the solutions seem to work.

@rmnbod can you please show us your test scripts and package.json? We'll be able to have a look..

@rmnbod
Copy link

rmnbod commented Aug 20, 2020

Having the same problem having latest packages installed, none of the solutions seem to work.

@rmnbod can you please show us your test scripts and package.json? We'll be able to have a look..

...
"react-scripts": "^3.4.3",`
"@testing-library/jest-dom": "^5.11.3",  
"@testing-library/react": "^10.4.8",  
"@testing-library/user-event": "^12.1.1",  
"ts-jest": "^26.2.0",  
"typescript": "^3.9.7"  
...
import React from "react";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import Dashboard from "../index";
import store from '../../../app/store'
import { screen, render } from "@testing-library/react";

jest.mock("../../../services/api/api-client-ts")

it('updates user data', async () => {
    render(
        <Provider store={store}>
            <BrowserRouter>
                <Dashboard/>
            </BrowserRouter>
        </Provider>
    )

    expect(await screen.findByText('fn ln'))
})

Fails with TypeError: MutationObserver is not a constructor exception.

At the end though managed it to work with MutationObserver polyfill, react-scripts test --env=jest-environment-jsdom-sixteen is of no avail.

@MatanBobi
Copy link
Member

At the end though managed it to work with MutationObserver polyfill, react-scripts test --env=jest-environment-jsdom-sixteen is of no avail.

Sorry, I didn't understand that, you're saying it doesn't work?

As you can see in @kentcdodds's comment here, you can either shim it yourself our use jest-environment-jsdom-sixteen..

@kentcdodds
Copy link
Member

Also react-scripts v4 is in alpha right now and it works without any extra effort FYI. It's awesome.

@nickserv
Copy link
Member

Can this be closed? It seems like the known issues in this thread have been solved.

@KevinBurton
Copy link
Author

KevinBurton commented Aug 24, 2020 via email

@paramsinghvc
Copy link

The solution of "test": "react-scripts test --env=jest-environment-jsdom-sixteen", works fine for Mutation Observer error but if we use it with --coverage flag as
"test": "react-scripts test --env=jest-environment-jsdom-sixteen --coverage",
it gives errors as

 console.error node_modules/jest-environment-jsdom-sixteen/node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Uncaught [Error: App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.]

@MatanBobi
Copy link
Member

@paramsinghvc does this happen for the same test that passed without the --coverage flag? The error doesn't seem coverage related to me..
If it does, can you please try and upgrade react-scripts to next and let us know if this still reproduces?

@paramsinghvc
Copy link

Without the --coverage flag, it works fine. I figured out a fix, by using react-scripts test --env=jsdom-fourteen --coverage instead of sixteen.

@ghost
Copy link

ghost commented Oct 18, 2020

Its October.
Fix according to developer and seems to work fine in my latest CRA project
npm install react-scripts@next

"MutationObserver need jsdom 16

in v4 of react-scripts uses that by default"

You can also update testing library with npm-check-updates (works for yarn too )

npm install -g npm-check-updates
ncu ( see what deps can be updated )
ncu -u ( update said deps in package.json )
yarn or npm install 

https://github.com/raineorshine/npm-check-updates

@woudsma
Copy link

woudsma commented Dec 8, 2020

As this one doesn't seem to be mentioned here yet, I took my fix from an answer on this issue:
testing-library/dom-testing-library#477 (comment)

Install jest-environment-jsdom:

npm i -D jest-environment-jsdom

Add to package.json:

"resolutions": {
  "jest-environment-jsdom": "^26.0.1"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests