aurelia 测试的不确定性单元测试问题

Underterministic unit-test issues with aurelia-testing

此问题与 有关。我正在简要地重复一些细节。我想对我的 aurelia 自定义元素进行单元测试,如下所示。

// BaseText.ts
import { bindable } from "aurelia-framework";
import { BaseI18N } from "aurelia-i18n";

export class BaseText extends BaseI18N {
    @bindable public value: string;
    @bindable public i18nKey: string;
}

// NormalText.html; NormalText inherits from BaseText
<template>
    <span t.bind="i18nKey">${value}</span>
</template>

// ValueText.html; ValueText inherits from BaseText
<template>
    <strong t.bind="i18nKey">${value}</strong>
</template>

现在,我想测试这些自定义元素的视图,它们具有以下形式。

describe("View specs", () => {

    it("Should render the text in a strong element without any additional style", (done) => {
        const randomId = randomIdGenerator();
        const component = StageComponent
            .withResources("ValueText/ValueText")
            .inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);

        component
            .create(bootstrap)
            .then(() => {
                const strongElement: HTMLElement = document.querySelector(`value-text#${randomId}>strong`);
                console.log(strongElement);
                expect(strongElement).toBeDefined();
                expect(strongElement.style.cssText).toBeFalsy();
                expect(Array.from(strongElement.classList).filter(item => !item.startsWith("au-")).length).toBe(0);
            })
            .catch(e => { console.log(e.toString()) })
            .finally(() => {
                component.dispose();
                done();
            });
    });

    it("Should render a dynamic text", (done) => {
        const randomId = randomIdGenerator();
        const component1 = StageComponent
            .withResources("ValueText/ValueText")
            .inView(`<value-text id='${randomId}' value.bind='boundValue'></value-text>`)
            .boundTo({ boundValue: "Hello Value Text" });

        component1
            .create(bootstrap)
            .then(() => {
                const strongElement = document.querySelector(`value-text#${randomId}>strong`);
                expect(strongElement.textContent.trim()).toBe('Hello Value Text');
            })
            .catch(e => { console.log(e.toString()) })
            .finally(() => {
                component1.dispose();
                done();
            });
    });

    it("Should render the provided static text without i18nKey", (done) => {
        const randomId = randomIdGenerator();
        const component2 = StageComponent
            .withResources("ValueText/ValueText")
            .inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);

        component2
            .create(bootstrap)
            .then(() => {
                const strongElement = document.querySelector(`value-text#${randomId}>strong`);
                expect(strongElement.textContent.trim()).toBe('Hello Static Text');
            })
            .catch(e => { console.log(e.toString()) })
            .finally(() => {
                component2.dispose();
                done();
            });
    });

});

虽然我在这里展示了 ValueText 的测试,但 NormalText 的测试看起来也非常相似。

当我 运行 分别针对这两个元素进行测试时,所有测试 运行 都很好。但是,当它们一起 运行 时,对于某些测试用例,document.querySelector('...') 会返回 undefined 元素。这导致 运行 没有 expect 断言。这导致了以下错误。

Spec 'HERE_GOES_SPEC_NAME' has no expectations.

经过一些调试,似乎当测试 运行 在一起时,对于第二个 运行 的测试套件,甚至没有创建自定义元素的视图。它创建一个 DOM 元素,如下所示。

<normal-text value="Hello Static Text"></normal-text>

但是缺少视图的 innerHTML 部分。更正式地说,在这些测试期间,关联的 viewmodel/controller 在 aurelia-templating 中仍然缺失,这导致了格式错误的视图。

我应该改变什么,使这些测试用例变得确定?

附加信息: 我创建了一个 GitHub repo,以便有兴趣的 reader/user 可以重现该问题。请记住,您可能 运行 多次测试以重现问题。

经过长时间的调试,事实证明,对于失败的测试规范(即 运行 秒后的测试套件),元数据是不正确的。例如,如果 NormalText 的测试套件首先是 运行,那么对于 ValueText 的测试套件,ValueText 的元数据反映了 NormalText 的元数据;更具体地说,NormalText.

的 HTML(查看)资源

可能某处有错误或我编写测试的方式有问题。

但是,我找到了一个简单的解决方法,即在两个 类 上应用 @customElement("element-name") 装饰器。这确实解决了问题。