I realise that this question has been asked on a number of occasions, though the environment has changed since those questions where asked: notably, JSDom now supports custom elements.
These other questions revolved around seeking alternatives (such as using Happy Dom) as JSDom did not support custom elements at that time. However, now that JSDom does support custom elements, does anyone have any information that can solve the following error?
TypeError: Class constructor HTMLElement cannot be invoked without 'new' 1 | export default class Foo extends HTMLElement { 2 | constructor() { > 3 | super(); | ^ 4 | 5 | this._clicker = 2; 6 | } at new Foo (__tests__/fooclass.js:3:5) at Object.<anonymous> (__tests__/fooclass.test.js:7:13)
A reference repo is available here (now fixed):
class Foo extends HTMLElement {
constructor() {
super();
this._clicker = 2;
}
connectedCallback() {
this.textContent = 'My Foo Bar Element';
}
get testCallback() {
return 'hello world!';
}
set clicker(num) {
this._clicker = Number(num);
}
get clicker() {
return this._clicker;
}
}
{
"scripts": {
"test": "jest --env=jest-environment-jsdom-sixteen"
},
"jest": {
"verbose": true
},
"devDependencies": {
"@babel/preset-env": "^7.8.4",
"babel-plugin-transform-builtin-classes": "^0.6.1",
"jest": "^25.1.0",
"jest-environment-jsdom-sixteen": "^1.0.2"
}
}
{
"presets": ["@babel/preset-env"]
}
Thanks to JSDOM, you can run your tests in Jest, which, as I have mentioned, can only run in Node. By using passing the value "jsdom" to Jest's testEnvironment option, you can make it set up a global instance of JSDOM which you can use when running your tests.
Jest actually ships with jsdom and the environment already configured. You can override it with the testEnvironment setting. If you need to set up more aspects of the environment though, you can use the setupTestFrameworkScriptFile setting to point to a file that executes before all of your tests run.
jsdom is a pure JavaScript implementation of the DOM and browser APIs that runs in node. If you're not using Jest and you would like to run your tests in Node, then you must install jsdom yourself. There's also a package called global-jsdom which can be used to setup the global environment to simulate the browser APIs.
TLDR It is possible to test web components with Jest. Don't use JSDOM but run your tests in a browser environment instead. But first things first, let's set up our project and see the component which we are going to test.
NOTE: As of May 2020, Jest supports JSDom 16.* by default, rendering the below no longer necessary or relevant
Jest runs with JSDom ^15.1.1
by default (as of Feb 17th, 2020) so you will need to update manually to use JSDom 16.2.0
installing jest-environment-jsdom-sixteen
.
First, install the latest JSDom environment for Jest
npm i jest-environment-jsdom-sixteen --save-dev
And change your package.json
to include:
"scripts": {
"test": "jest --env=jest-environment-jsdom-sixteen"
},
This will ensure that Jest is running the correct environment.
You will also need to ensure that Babel correctly handles built-in classes (e.g. class HTMLElement {}
) by installing babel-plugin-transform-builtin-classes
, like so:
npm i babel-plugin-transform-builtin-classes --save-dev
And added to your .babelrc
the following
"plugins": [
["babel-plugin-transform-builtin-classes", {
"globals": ["Array", "Error", "HTMLElement"]
}]
]
Do not install babel-plugin-transform-es2015-classes
as this already forms part of the Babel 7 core, as per this issue
Working reduced test case available here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With