Как правильно заглушить элемент при модульном тестировании компонента LitElement?

#typescript #unit-testing #mocking #mocha.js #lit-element

#typescript #модульное тестирование #издевательство #mocha.js #lit-элемент

Вопрос:

Я пытаюсь выполнить модульное тестирование компонентов LitElement. При попытке изолировать компоненты я был озадачен тем, как на самом деле заглушить элементы. То есть я не могу найти решение, как заменить правильный элемент на выдолбленный.
В проекте polymer по теме модульного тестирования упоминается следующее: мне не удалось найти определение функции replace(), чтобы увидеть детали реализации. На самом деле, то, что описано в проекте polymer в заголовке «Создание элементов-заглушек», — это то, что я ищу.

Файл определения элемента

 export class AppElement extends LitElement {
    render() {
        return html`
            <header-element class="header"></header-element>
            <div class="body">
                <menu-element></menu-element>
                <social-media-element></social-media-element>
                <contacts-element></contacts-element>
                <tap-list-element name="Fridge List" display="fridge"></tap-list-element>
                <tap-list-element route="tap" name="Tap List" display="tap" ></tap-list-element>
                <home-element></home-element>
                <about-us-element></about-us-element>
                <not-found-element></not-found-element>
            </div>
       `;
   }
}
 

Файл тестирования элемента

 describe("Test Case for the AppElement Component", function() {
beforeEach(() => {
    app = new AppElement();
    document.body.appendChild(app);
    shadow = app.shadowRoot;
    app.updateComplete.then(() => {
        const tapListStub = new TapListElementStub();
        const tapListNodes = shadow.querySelectorAll('tap-list-element');
        console.log(app);
        const tapListLength = tapListNodes.length;
        const tapListNode = tapListLength === 1 ? tapListNodes[0] : null;
        tapListNode.replaceWith(tapListStub);
    });
});

it("should have the node for tap-list replaced with a stub", function(done) {
    app.updateComplete.then(() => {
        const newTap: TapListElement = shadow.querySelector('tap-list-element');
        console.log(shadow);
        assert.strictEqual('Tap List Stub', newTap.name);
        done();
    })
});
 

Вот код для исходного TapListElement

 @customElement('tap-list-element')
export class TapListElement extends LitElement {
    private _menu: Menu;
    private _tapList: Section;
    private _bottleList: Section;

    @property()
    name: string = 'Tap List';

    @property({type: String, attribute: true})
    display: string;

    constructor() {
        super();
        super.connectedCallback();
    }
}
 

А вот и заглушка

 @customElement('tap-list-element')
export class TapListElementStub extends LitElement {

    @property()
    name: string = 'Tap List Stub';

    @property({type: String, attribute: true})
    display: string;

    constructor() {
        super();
        super.connectedCallback();
    }
}
 

Приносим извинения за любые опечатки отступов.

Когда я попробовал приведенный выше код, я получаю сообщение об ошибке, что веб-компонент с таким именем «tap-list-element» уже зарегистрирован. Я попытался удалить декоратор @CustomElement в TapListElementStub, но затем я получаю сообщение об ошибке, что был вызван недопустимый конструктор. Кто-нибудь пробовал заглушать компоненты LitElement? Я исхожу из Angular background. Там вспомогательная библиотека TestBed настраивает модуль, и вы можете заменить любой компонент, если атрибуты остаются неизменными, а имя компонента в декораторе остается тем же.

Ответ №1:

Первая ошибка, вероятно, вызвана <tap-list-element> тем, что она была определена дважды в двух версиях. Этого нельзя избежать, поскольку на данный момент пользовательские элементы не являются неопределяемыми (и, следовательно, могут быть переопределены с помощью другого класса). Удаление регистрационного вызова, как вы пытались, не решает проблему, потому что компонент все равно будет создан с использованием исходного класса.

Самым простым решением было бы использовать другое имя тега (даже документы Polymer, на которые вы ссылались, делают это). Если вам действительно нужно, чтобы имена тегов были одинаковыми, то я могу предложить заменить только некоторые свойства / методы исходного класса. В руководствах по OpenWC и современному веб-тестированию есть несколько частей (1, 2), посвященных этому.

Комментарии:

1. Спасибо. Ресурсы, на которые вы ссылаетесь, являются идеальной отправной точкой. Я думаю, что каким-то образом реализация import-maps решит мою проблему.