我想测试一些自定义的Web组件,并使用jest.js作为测试运行器(由于它支持ES6)。
Chromium支持以下命令
window.customElements.define('my-custom-element', MyCustomElementClass);
注册自定义Web组件。
然而,window.customElements
在jest测试的上下文中似乎是未知的。
作为一个变通方案,我尝试使用jest结合puppeteer和express来运行Chromium中的customElements
部分。
然而,我很难在评估的代码中注入自定义元素类TreezElement
:
treezElement.js:
class TreezElement extends HTMLElement {
connectedCallback () {
this.innerHTML = 'Hello, World!';
}
}
treezElement.test.js:
import TreezElement from '../../src/components/treezElement.js';
import puppeteer from 'puppeteer';
import express from 'express';
describe('Construction', ()=>{
let port = 3000;
let browser;
let page;
let element;
const width = 800;
const height = 800;
beforeAll(async () => {
const app = await express()
.use((req, res) => {
res.send(
`<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
</html>`
)
})
.listen(port);
browser = await puppeteer.launch({
headless: false,
slowMo: 80,
args: [`--window-size=${width},${height}`]
});
var pages = await browser.pages();
page = pages[0];
await page.setViewport({ width, height });
await page.goto('http://localhost:3000');
element = await page.evaluate(({TreezElement}) => {
console.log('TreezElement:')
console.log(TreezElement);
window.customElements.define('treez-element', TreezElement);
var element = document.create('treez-element');
document.body.appendChild(element);
return element;
}, {TreezElement});
});
it('TreezElement', ()=>{
});
afterAll(() => {
browser.close();
});
});
也许TreezElement
是不可序列化的,因此undefined
被传递给函数。
如果我尝试直接从评估的代码中导入自定义元素类TreezElement
…
element = await page.evaluate(() => {
import TreezElement from '../../src/components/treezElement.js';
console.log('TreezElement:')
console.log(TreezElement);
window.customElements.define('treez-element', TreezElement);
var element = document.create('treez-element');
document.body.appendChild(element);
return element;
});
我得到了错误
'import'和'export'只能出现在顶层
=〉使用jest测试自定义Web组件的推荐方法是什么?
一些相关的东西:
5条答案
按热度按时间s4chpxco1#
JSDOM 16.2包括对自定义元素的基本支持,并且在Jest 26.5及更高版本中可用。下面是一个简单的Jest测试,显示它的工作情况:
输出:
注意,并非所有功能都支持,特别是shadow DOM不工作。
8zzbczxx2#
我已经创建了一个DOM,它支持服务器端呈现Web组件,还支持使用Jest测试Web组件。
DOM:
https://www.npmjs.com/package/happy-dom
Jest环境:
https://www.npmjs.com/package/jest-environment-happy-dom
安装
npm install jest-environment-happy-dom --save-dev
使用方法:
编辑package.json以包含Jest环境:
编辑:
包的名称已更改为“@happy-dom/jest-environent”
uoifb46i3#
使用electron runner可以包含所有的node和chrome env,用这个来代替jsdom
https://github.com/facebook-atom/jest-electron-runner
6ioyuze24#
这里有一个丑陋的版本,有点工作。一些进一步的说明:
TreezElement
不是直接导入的,而是通过创建一个额外的脚本标记来实现的。TreezElement
的构造函数(继承自HTMLElement,=〉illegal constructor
),在puppeteer中只有document.createElement(...)
才能创建元素类的示例,因此,所有的示例方法都不能在Jest中测试,只能测试静态方法。示例方法和属性可以在puppeteer中测试。但是,the code coverage of jest does not consider the code coverage of puppeteer。TreezElement
类型的元素可以以ElementHandle的形式返回。访问元素示例的属性和方法非常麻烦(见下面的示例)。作为句柄方法的替代方案,可以应用page.$eval
方法:index.html
treezElement.test.js
uxhixvfz5#
另一种(有限的)方法是使用
Object.create
作为一种解决方案来创建自定义Web组件的示例,而不使用window.customElements.define
和document.createElement(..)
:这样,示例方法可以直接在jest中测试,并且测试也包含在代码覆盖率中。(也是我关于puppeteer的另一个答案的覆盖率问题。)
一个主要的缺点是只能访问方法,不能访问属性。如果我尝试使用customElement.customProperty,我会得到:
TypeError: Illegal invocation
。这是由Element.js中的
!module.exports.is(this)
检查引起的:Object.create
的另一个缺点是构造函数代码不被调用,也不包括在测试覆盖中。如果命令
window.customElements.define(..)
直接包含在我们想要导入的类文件中(例如treezElement.js)...在包含导入之前需要模拟customElements
属性:customElementsMock.js:
treezElement.test.js中的用法:
(我也尝试将mock代码直接放在
treezElement.test.js
的开头,但是all the imports are executed prior to the script doing the import。这就是为什么我必须将mock代码放在一个额外的文件中。)