How to test custom web component with jest?

后端 未结 5 735
栀梦
栀梦 2021-01-06 08:54

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         


        
5条回答
  •  半阙折子戏
    2021-01-06 09:11

    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.)

提交回复
热议问题