I would like to test some custom web components and use jest.js as test runner (due to its support for ES6).
Chromium supports commands like
window.customElements.define('my-custom-element', MyCustomElementClass);
to register a custom web component.
However, window.customElements
does not seem to be known in the context of jest tests.
As a work around I tried to use jest in combination with puppeteer and express to run the customElements
part in Chromium.
However, I have difficulties to inject the custom element class TreezElement
in the evaluated code:
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();
});
});
Maybe TreezElement
is not serializable and therefore undefined
is passed to the function.
If I try to import the custom element class TreezElement
directly from within the evaluated code ...
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;
});
... I get the error
'import' and 'export' may only appear at the top level
=> What is the recommended way to test custom web components with jest?
Some related stuff:
Web Component / HtmlElement : unit testing
https://itnext.io/testing-your-javascript-in-a-browser-with-jest-puppeteer-express-and-webpack-c998a37ef887
How to mock dependencies for ES6 unit tests?
Can't get test coverage with jest + puppeteer
https://jestjs.io/docs/en/puppeteer
TLDR It is possible to test web components with Jest. Don't use JSDOM but run your tests in a browser environment instead.
The Web Component Test Execution Environment As of writing this, the only viable way of running tests for Web Components is through Karma which executes them through a target browser. People coming from current technologies, such as React, Angular or Vue, might be disappointed with the current state of matters.
JSDOM 16.2 includes basic support for custom elements and is available in Jest 26.5 and above. Here's a simple Jest test that shows it working:
customElements.define('test-component', class extends HTMLElement {
constructor() {
super();
const p = document.createElement('p')
p.textContent = 'It works!'
this.appendChild(p)
}
})
test('custom elements in JSDOM', () => {
document.body.innerHTML = `<h1>Custom element test</h1> <test-component></test-component>`
expect(document.body.innerHTML).toContain('It works!')
})
Output:
$ jest
PASS ./test.js
✓ custom elements in JSDOM (11 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.409 s
Ran all test suites.
Note not all features are supported yet, notably shadow DOM does not work.
I have created a DOM that supports server side rendering of web components. It also supports testing web components with Jest.
DOM:
https://www.npmjs.com/package/happy-dom
Jest environment:
https://www.npmjs.com/package/jest-environment-happy-dom
To install it
npm install jest-environment-happy-dom --save-dev
To use it:
Edit your package.json to include the Jest environment:
{
"scripts": {
"test": "jest --env=jest-environment-happy-dom"
}
}
use electron runner can include all node and chrome env, use this to replace jsdom
https://github.com/facebook-atom/jest-electron-runner
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