如何使用 JSDom 对 Jest 中的自定义元素执行单元测试

Oli*_*ver 6 unit-testing jsdom jestjs custom-element babeljs

我意识到这个问题已经被问过很多次了,尽管自从提出这些问题以来环境已经发生了变化:值得注意的是,JSDom 现在支持自定义元素

这些其他问题都围绕着寻找替代方案(例如使用Happy Dom),因为当时 JSDom 不支持自定义元素。但是,既然JSDom确实支持自定义元素,那么有没有人有任何信息可以解决以下错误?

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)
Run Code Online (Sandbox Code Playgroud)

当前设置:

此处提供参考仓库(现已修复):

自定义元素示例

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;
  }
}

Run Code Online (Sandbox Code Playgroud)

包.json

{
  "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"
  }
}
Run Code Online (Sandbox Code Playgroud)

.babelrc

{
  "presets": ["@babel/preset-env"]
}
Run Code Online (Sandbox Code Playgroud)

Oli*_*ver 2

注意:截至2020 年 5 月,Jest 默认支持 JSDom 16.*,因此以下内容不再必要或相关

解决方案

Jest 默认使用 JSDom 运行^15.1.1(截至2020 年 2 月 17 日),因此您需要手动更新才能使用 JSDom16.2.0安装jest-environment-jsdom-sixteen

首先,为Jest安装最新的JSDom环境

npm i jest-environment-jsdom-sixteen --save-dev
Run Code Online (Sandbox Code Playgroud)

并更改您的内容package.json以包括:

"scripts": {
  "test": "jest --env=jest-environment-jsdom-sixteen"
},
Run Code Online (Sandbox Code Playgroud)

这将确保 Jest 运行在正确的环境中。

您还需要通过安装来确保 Babel 正确处理内置类(例如class HTMLElement {}babel-plugin-transform-builtin-classes,如下所示:

npm i babel-plugin-transform-builtin-classes --save-dev
Run Code Online (Sandbox Code Playgroud)

并添加到您的.babelrc以下内容

"plugins": [
  ["babel-plugin-transform-builtin-classes", {
    "globals": ["Array", "Error", "HTMLElement"]
  }]
]
Run Code Online (Sandbox Code Playgroud)

不要安装,因为babel-plugin-transform-es2015-classes这已经成为 Babel 7 核心的一部分,根据这个问题

此处提供了工作简化测试用例。