Как протестировать веб-компонент (светящийся элемент) с помощью шутки

У кого-нибудь есть хорошая настройка для тестирования пользовательских элементов с помощью jest, jsdom или аналогичных? Я использовал Puppeteer и Selenium, но они слишком сильно замедляют выполнение тестов. Есть ли другие альтернативы или исправления для jsdom, которые делают следующий тест работоспособным?

import {LitElement} from 'lit-element';
import {html} from 'lit-html';

export class Counter extends LitElement {
  static get properties() {
    return Object.assign({}, super.properties, {
      count: {type: Number}
    });
  }

  render() {
    return html`Count is ${this.count}`;
  }
}

customElements.define('c-counter', Counter);

С тестовым файлом:

import './counter';

describe('c-counter', () => {
  it('should be registered', () => {
    expect(customElements.get('c-counter')).toBeDefined();
  });

  it('render', async () => {
    const element = window.document.createElement('c-counter');
    window.document.body.appendChild(element);

    await element.updateComplete;
    expect(element.innerHTML).toContain('Count is undefined');

    element.count = 3;
    await element.updateComplete;

    expect(element.innerHTML).toContain('Count is 3');
  });
});

И, наконец, это текущая настройка среды шутки:

const {installCommonGlobals} = require('jest-util');
const {JSDOM, VirtualConsole} = require('jsdom');
const JSDOMEnvironment = require('jest-environment-jsdom');
const installCE = require('document-register-element/pony');

class JSDOMCustomElementsEnvironment extends JSDOMEnvironment {
  constructor(config, context) {
    super(config, context);

    this.dom = new JSDOM('<!DOCTYPE html>', {
      runScripts: 'dangerously',
      pretendToBeVisual: true,
      VirtualConsole: new VirtualConsole().sendTo(context.console || console),
      url: 'http://jsdom'
    });

    /* eslint-disable no-multi-assign */
    const global = (this.global = this.dom.window.document.defaultView);

    installCommonGlobals(global, config.globals);

    installCE(global.window, {
      type: 'force',
      noBuiltIn: false
    });
  }

  teardown() {
    this.global = null;
    this.dom = null;

    return Promise.resolve();
  }
}

module.exports = JSDOMCustomElementsEnvironment;

person tirithen    schedule 14.03.2019    source источник
comment
Было бы полезно, если бы вы рассказали, в чем ошибка. А поскольку так мало людей, если таковые имеются, запускают тесты веб-компонентов в Jest, я бы, вероятно, попытался создать репозиторий или репозиторий, чтобы люди могли попробовать.   -  person Justin Fagnani    schedule 14.03.2019
comment
Я не ожидаю, что это будет хорошо, пока jsdom не будет поддерживать настраиваемые элементы и модули JS. Учитывая большое количество DOM API, которые используют веб-компоненты, я считаю, что тестирование в реальном браузере является гораздо более разумным подходом. Вам следует протестировать все существующие браузеры, которые вы поддерживаете.   -  person Justin Fagnani    schedule 14.03.2019
comment
Я полностью согласен с Джастином в этом ... если вам нужна помощь в настройке тестирования в реальном браузере, посмотрите здесь open-wc.org/testing - это должно быть довольно просто и предоставляет вам большинство функций, которые вы знаете из Jest, в реальном браузере.   -  person daKmoR    schedule 02.04.2019
comment
@JustinFagnani, я ищу хороший стек для тестирования обычных веб-компонентов (здесь вы найдете несколько моих вопросов по этой теме). Вы сказали, что несколько человек запускают тестирование веб-компонентов в Jest. Знаете ли вы, за / против использования Jest для тестирования веб-компонентов? Не поймите меня неправильно, но просто сказать, что немногие используют ... мало помогает (вы найдете много людей, которые говорят, что не многие люди используют веб-компоненты. Я использую Polymer с заметным успехом, и теперь я пробую ванильный веб -компоненты). Немного / много / много / и т. Д. Мало что добавляет, но если вы можете вкратце указать, почему бы и нет   -  person Jim C    schedule 11.07.2019
comment
Я сам испытываю проблемы с этим   -  person Josh    schedule 17.05.2020
comment
@Josh Проект, в котором я использовал это, движется к использованию open-wc.org вместо этого, поскольку этот проект активен и имеет тестирование с настройкой покрытия из коробки и по-прежнему использует LitElement для веб-компонентов. Вероятно, это лучший способ провести тестирование с LitElement.   -  person tirithen    schedule 20.05.2020


Ответы (1)


Это возможно с небольшой дополнительной настройкой.

Если вы посмотрите открытую документацию wc, они рекомендуют тестировать ваши веб-компоненты в браузере, что они уже делают с Karma и Headless Chrome. Как вы уже отметили, Puppeteer и Selenium слишком медленны для этого, и единственной жизнеспособной альтернативой браузеру является ElectronJS. Для Jest доступен раннер.

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

Это позволит вам отображать ваши веб-компоненты в реальном браузере с доступом к Shadow DOM, и ваши тесты по-прежнему будут быстрыми. Примерно так я использую Webpack для обработки своего кода.

// button.ts
import {html, customElement, LitElement, property} from "lit-element";

@customElement('awesome-button')
export class Button extends LitElement {

    @property()
    buttonText = '';

    render() {
        return html`<button id="custom-button"
            @click="${() => {}}">${this.buttonText}</button>`;
    }
}

Конфигурация Webpack

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

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

И наконец наш тест.

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);
    });
});

Я даже написал об этом в блоге, и там вы можете найти репозитории с полной настройкой и т. Д.

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

person Wizard    schedule 05.06.2020
comment
Как мне добавить журналы покрытия кода, вроде кармы в этом? - person Matheus Ribeiro; 29.06.2021
comment
@MatheusRibeiro Jest имеет множество опций для настройки покрытия кода различными репортерами. См. Документацию. jestjs.io/docs/configuration#collectcoverage-boolean - person Wizard; 01.07.2021