How to test Web Component (lit-element) with jest

后端 未结 1 701
庸人自扰
庸人自扰 2021-02-08 11:38

Anyone has a good setup for testing custom elements with jest, jsdom or similar? I have been using Puppeteer and Selenium, but they slow down the test runs too much. Any other a

1条回答
  •  生来不讨喜
    2021-02-08 12:23

    It is possible with a bit of additional setup.

    If you look at open wc docs, they recommend testing your web components in the browser which they already do with Karma and Headless Chrome. As you already pointed out Puppeteer and Selenium are too slow for this and the only viable browser alternative is ElectronJS. There is a runner available for Jest.

    https://github.com/hustcc/jest-electron

    This will allow you to render your web components in a real browser with access to Shadow DOM and your tests will still be fast. Something like this, I use Webpack for processing my code.

    // button.ts
    import {html, customElement, LitElement, property} from "lit-element";
    
    @customElement('awesome-button')
    export class Button extends LitElement {
    
        @property()
        buttonText = '';
    
        render() {
            return html``;
        }
    }

    Webpack configuration

    const path = require('path');
    const {CleanWebpackPlugin} = require('clean-webpack-plugin');
    
    module.exports = {
        mode: 'development',
        entry: './index.ts',
        module: {
            rules: [
                {
                    test: /\.ts?$/,
                    use: 'ts-loader',
                    exclude: /node_modules/,
                },
            ],
        },
        resolve: {
            extensions: ['.tsx', '.ts', '.js'],
        },
        plugins: [
            new CleanWebpackPlugin()
        ],
        output: {
            filename: 'main.js',
            path: path.resolve(__dirname, 'dist'),
        },
    };

    Jest configuration

    module.exports = {
        preset: 'ts-jest',
        runner: 'jest-electron/runner',
        testEnvironment: 'jest-electron/environment',
        setupFiles: ['./dist/main.js'],
    };

    And finally our test.

    import {LitElement} from 'lit-element';
    
    describe('awesome-button', () => {
    
        const AWESOME_BUTTON_TAG = 'awesome-button';
        const ELEMENT_ID = 'custom-button';
        let buttonElement: LitElement;
    
        const getShadowRoot = (tagName: string): ShadowRoot => {
            return document.body.getElementsByTagName(tagName)[0].shadowRoot;
        }
    
        beforeEach(() => {
            buttonElement = window.document.createElement(AWESOME_BUTTON_TAG) as LitElement;
            document.body.appendChild(buttonElement);
        });
    
        afterEach(() => {
           document.body.getElementsByTagName(AWESOME_BUTTON_TAG)[0].remove();
        });
    
        it('displays button text', async () => {
            const dummyText = 'Web components & Jest with Electron';
            buttonElement.setAttribute('buttonText', dummyText);
            await buttonElement.updateComplete;
    
            const renderedText = getShadowRoot(AWESOME_BUTTON_TAG).getElementById(ELEMENT_ID).innerText;
    
            expect(renderedText).toEqual(dummyText);
        });
        it('handles clicks', async () => {
            const mockClickFunction = jest.fn();
            buttonElement.addEventListener('click', () => {mockClickFunction()});
    
            getShadowRoot(AWESOME_BUTTON_TAG).getElementById(ELEMENT_ID).click();
            getShadowRoot(AWESOME_BUTTON_TAG).getElementById(ELEMENT_ID).click();
    
            expect(mockClickFunction).toHaveBeenCalledTimes(2);
        });
    });

    I even wrote a blog post about this and there you can find repos with the full setup etc.

    https://www.ninkovic.dev/blog/2020/testing-web-components-with-jest-and-lit-element

    0 讨论(0)
提交回复
热议问题