Jest: Expect dies with "ReferenceError: Element is not defined" in "node" test environment

Created on 3 Feb 2019  路  6Comments  路  Source: facebook/jest

馃悰 Bug Report

When running tests with "testEnvironment": "node" and expect determines via duck typing that it has DOM nodes to compare it throws ReferenceError: Element is not defined since Element isn't available in Node.

To Reproduce

Use "testEnvironment": "node" and run this test

describe("reproduce bug", () => {
    it("should know that inside a 'node' env there is no 'Element' in scope", () => {
        expect({ nodeName: "div", nodeType: 1 })
            .toEqual({ nodeName: "div", nodeType: 1 });
    });
});

The most likely culprit in my opinion is this region where it was determined per duck typing that the things to compare are DOM nodes and then an unguarded instanceof Element check is run https://github.com/facebook/jest/blob/master/packages/expect/src/jasmineUtils.js#L134

Expected behavior

It should always check that Element or any other host object is defined before it is used - so the test above should be green.

Link to repl or repo (highly encouraged)

https://repl.it/repls/PureFrightenedIntegers

Run npx envinfo --preset jest

Paste the results here:

> npx envinfo --preset jest
npx: installed 1 in 3.224s

  System:
    OS: Linux 4.15 Ubuntu 18.04.1 LTS (Bionic Beaver)
    CPU: (4) x64 Intel(R) Core(TM) i3-5005U CPU @ 2.00GHz
  Binaries:
    Node: 8.10.0 - /usr/bin/node
    npm: 6.7.0 - /usr/local/bin/npm
  npmPackages:
    jest: ^24.0.0 => 24.0.0 
Bug

All 6 comments

Wanna send a PR for it?

/cc @pedrottimark

This code in vue-test-utils.js fails (@vue/test-utils 1.0.0-beta.31). Just installed today released jest 25.1.0 and ts-jest 25.0.0 with vue-jest 3.0.5 (latest)

function polyfill() {
  // Polyfill `Element.matches()` for IE and older versions of Chrome:
  // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
  if (!Element.prototype.matches) {
    Element.prototype.matches =
      Element.prototype.msMatchesSelector ||
      Element.prototype.webkitMatchesSelector;
  }
}

This was fixed in #7995 (included in 24.3.0), and we just forgot to close this issue.

@postb99 could you please open up a new issue with reproduction steps? https://repl.it/repls/PureFrightenedIntegers does not reproduce using 24.9.0 or 25.1.0 for me, so I think your issue is different somehow.

@SimenB Thanks. I just fixed it... By installing jsdom-global as stated here: https://vue-test-utils.vuejs.org/guides/#choosing-a-test-runner despite it should have been set up automatically.

So I may open an issue but I think I misread something in documentation... How to find the culprit ?

So the relevant packages for my setup are these ones. I write .vue components using typescript, and now Jest runs the test fine. The test code is also written in ts.

"devDependencies": {
    "@babel/plugin-transform-modules-commonjs": "^7.8.3",
    "@types/jest": "^24.9.0",
    "@types/jsdom": "^12.2.4",
    "@vue/cli-plugin-babel": "^4.1.2",
    "@vue/cli-plugin-typescript": "^4.1.2",
    "@vue/cli-plugin-unit-jest": "^4.1.2",
    "@vue/cli-service": "^4.1.2",
    "@vue/test-utils": "^1.0.0-beta.31",
    "babel-core": "^7.0.0-bridge.0",
    "babel-jest": "^25.1.0",
    "jest": "^25.1.0",
    "jsdom": "^16.0.1",
    "jsdom-global": "^3.0.2",
    "ts-jest": "^25.0.0",
    "typescript": "^3.7.5",
    "vue-jest": "^3.0.5",
    "vue-template-compiler": "^2.6.11"
  }

jest.config.js:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
    // before the test framework is installed
  setupFiles: ['./src/__mocks__/client.js'],
  moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'vue', 'node'],
  transform: {
    // process `*.vue` files with `vue-jest`
    '.*\\.(vue)$': 'vue-jest',
    // process `*.ts` files with `ts-jest`
    '^.+\\.ts?$': 'ts-jest',
    '^.+\\.(js|jsx)$': '<rootDir>/node_modules/babel-jest',
  },
  moduleNameMapper: {
  '^@/(.*)$': '<rootDir>/src/$1'
  },
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
  testURL: 'http://localhost/8081'
}

client.js :

require('jsdom-global')()

remove testEnvironment: 'node', (or set it to the default jsdom) and then you don't need jsdom-global anymore.

This works well and even speeds up my tests, 4 suites of 37 tests run in 7s instead of 10s when testEnvironment is set to "jsdom". I don't know why I missed the best testEnvironment to set in the documentation, In fact I did a copy-paste from a colleague's project, this was not the best idea.

Was this page helpful?
0 / 5 - 0 ratings