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

У кого-нибудь есть хорошая установка для тестирования пользовательских элементов с помощью 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');
  });
});

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

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;

Было бы полезно, если бы вы поделились, что это за ошибка. А так как так мало людей, если они вообще есть, запускают тесты веб-компонентов в Jest, я, вероятно, попытаюсь создать репродукцию в репозитории или суть, чтобы люди могли попробовать.

Justin Fagnani 14.03.2019 19:01

Я не ожидаю, что это будет здорово, пока jsdom не будет поддерживать пользовательские элементы и модули JS. Учитывая большое количество API-интерфейсов DOM, которые используют веб-компоненты, я думаю, что тестирование в реальном браузере — гораздо более разумный подход. Вы должны протестировать во всех реальных браузерах, которые вы поддерживаете.

Justin Fagnani 14.03.2019 19:02

Я полностью согласен с Джастином в этом... если вам нужна помощь в настройке тестирования в реальном браузере, посмотрите здесь open-wc.org/тестирование - это должно быть довольно прямолинейно и дает вам большинство функций, которые вы знаете из Jest, в реальном браузере.

daKmoR 02.04.2019 20:39

@JustinFagnani, я ищу хороший стек для тестирования ванильных веб-компонентов (здесь вы найдете несколько вопросов от меня по этой теме). Вы сказали: «Немногие люди тестируют веб-компоненты в Jest». Знаете ли вы сторонников и противников использования Jest для тестирования веб-компонентов? Не поймите меня неправильно, но простое высказывание «немногие используют...» мало чем поможет (вы обнаружите, что многие люди говорят, что мало кто использует веб-компоненты. Я использую Polymer со значительным успехом, и теперь я пытаюсь ванильные веб-компоненты). «Немного/много/много/и т. д. не добавляет многого, но если вы можете кратко указать, почему это не так,

Jim C 11.07.2019 18:36

сам испытываю с этим проблемы

Josh 17.05.2020 05:43

@Josh Проект, в котором я использовал это, движется к использованию open-wc.org вместо этого, поскольку этот проект активен и имеет готовое тестирование с настройкой покрытия и по-прежнему использует LitElement для веб-компонентов. Вероятно, это лучший способ тестирования с помощью LitElement.

tirithen 20.05.2020 15:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
6
7 219
1

Ответы 1

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

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

https://github.com/hustcc/jest-электрон

Это позволит вам отображать ваши веб-компоненты в реальном браузере с доступом к 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>`;
    }
}

Конфигурация веб-пакета

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

Конфигурация шутки

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

Как мне добавить журналы покрытия кода, например карму?

Matheus Ribeiro 29.06.2021 16:21

У @MatheusRibeiro Jest есть множество вариантов настройки покрытия кода разными репортерами. Пожалуйста, ознакомьтесь с документацией. jestjs.io/docs/configuration#collectcoverage-boolean

Wizard 01.07.2021 02:26

Другие вопросы по теме