如何在对 LitElement 组件进行单元测试时正确存根元素?

How to properly stub an element when unit testing a LitElement component?

我正在尝试对 LitElement 组件进行单元测试。在尝试隔离组件时,我对如何实际存根元素感到困惑。也就是说,我找不到如何用空心元素替换适当元素的解决方案。
关于单元测试主题的聚合物项目提到 this 我未能找到 replace() 函数的定义以查看实现细节。实际上,“创建存根元素”标题中的聚合物项目描述的正是我要找的。

元素定义文件

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”的 Web 组件已被注册。我尝试删除 TapListElementStub 中的 @customElement 装饰器,但随后出现错误,指出已调用非法构造函数。 有没有人尝试存根 litElement 组件? 我来自 Angular 背景。 TestBed 帮助程序库在那里设置模块,只要属性保持不变并且装饰器中的组件名称相同,您就可以替换任何组件。

第一个错误可能是由于<tap-list-element>在两个版本中定义了两次。这是无法避免的,因为到目前为止自定义元素是 not un-definable(因此可以用不同的 class 重新定义)。在您尝试时删除注册调用并不能解决问题,因为该组件仍将使用原始 class.

创建

最简单的解决方案是使用不同的标签名称(即使是您引用的 Polymer 文档也这样做)。如果您确实需要相同的标签名称,那么我的建议是仅替换原始 class 的一些 properties/methods。 OpenWC 和现代 Web 测试指南有一些部分 (1, 2) 专门用于此。