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.c
Another (limited) approach is to use Object.create as a work around to create an instance of the custom web component, without using window.customElements.define and document.createElement(..) :
import TreezElement from '../../src/components/treezElement.js';
var customElement = Object.create(TreezElement.prototype);
This way the instance methods can be tested directly in jest and the tests are included in the code coverage, too. (Also coverage issues of my other answer regarding puppeteer.)
A major disadvantage is that only the methods can be accessed, not the properties. If I try to use customElement.customProperty I get : TypeError: Illegal invocation.
This is caused by the check !module.exports.is(this) in Element.js:
Element.prototype.getAttribute = function getAttribute(qualifiedName) {
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
...
Element.prototype.setAttribute = function setAttribute(qualifiedName,value){
if (!this || !module.exports.is(this)) {
throw new TypeError("Illegal invocation");
}
Another disadvantage of Object.create is that the constructor code is not called and not included in the test coverage.
If the command window.customElements.define(..) is directly included in a class file that we would like to import (e.g. treezElement.js) ... the customElements property needs to be mocked before including the import:
customElementsMock.js:
export default class CustomElementsMock{} //dummy export
//following command mocks the customElements feature to be able
//to import custom elements in jest tests
window.customElements = {
define: (elementName, elementClass)=>{
console.log('Mocked customElements.define(..) for custom element "' + elementName + '"');
}
};
usage in treezElement.test.js:
import CustomElementsMock from '../customElementsMock.js';
import TreezElement from '../../src/components/treezElement.js';
var customElement = Object.create(TreezElement.prototype);
//...
(I also tried to put the mock code directly at the beginning of treezElement.test.js but all the imports are executed prior to the script doing the import. That is why I had to put the mocking code in an extra file.)