在 Stencil with Jest 中,如何使用模板测试组件上的对象 属性?

In Stencil with Jest, how to test object property on components using template?

我有一个看起来像这样的模板组件:

    export class MyBadge {
      @Prop() skin: string = 'primary';
      render(){
        return (
        <span class={`skin-${this.skin}`} />
      )

我想编写一个单元测试来检查呈现的组件是否应用了给定的 skin 属性。 我有一个测试将呈现的组件与我预期的 html 进行比较,使用 expect(page.root).toEqualHtml(´< span class=primary >´). 这个测试有效!但是,当我尝试使用模板修改 prop 时,运行 测试失败。

    import { newSpecPage } from '@stencil/core/testing';
    import { MyBadge } from './my-badge'
    it('should have "secondary" skin', async () => {
     const page = newSpecPage({
            components: [MyBadge],
            template: () => (`
              <my-badge skin=secondary></my-badge>
              `), 
          });
          expect(page.root).toEqualHtml(`
          <span class="skin-secondary">
          ...
          `);
        });

这给出错误 expect toEqualHtml() value is "null" 并且测试失败

我也试过在 it 下包含波纹管 html,但也失败了。

html: `<my-badge></my-badge>`,

删除模板选项使测试工作,但是它不会看到更新的属性。

我想根据这个答案使用模板选项: https://github.com/ionic-team/stencil/issues/1923

我也尝试了几种不同的语法,我不清楚如何包装模板字符串。

我一直在寻找这方面的文档,但似乎找不到我要找的东西。如有任何帮助,我们将不胜感激!

编辑: 根据@Simon Hänisch

的建议清理了代码

您的模板是 returning 字符串,而不是 JSX。您基本上会得到一个包含 <badge skin=secondary></badge> 作为字符串的文档,而不是实际的 badge 元素。

顺便说一句,badge 不是有效的自定义元素名称,它的名称中需要有一个破折号 (-)。您的示例代码中也存在语法错误,例如您的组件应该

return (
  <span class={`skin-${this.skin}`} />
)

(class 字符串的反引号丢失且标签未关闭)

假设所有这些都只是写这个问题时的错误,并且您的代码中实际上有一行 newSpecPage(这里也没有),这就是您需要做的:

  1. 将规范测试文件的扩展名更改为 .tsx
  2. 添加import { h } from '@stencil/core';.
  3. 编写一些实际的 JSX 作为模板的 return 值。
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { MyBadge } from './my-badge';

it('should have "secondary" skin', async () => {
  const page = newSpecPage({
    components: [MyBadge],
    template: () => <my-badge skin="secondary" />,
  });

  expect(page.root).toEqualHtml('<span class="skin-secondary"></span>');
});

你不能同时使用 templatehtml 这两个选项(或者至少它没有意义,我不确定哪个优先),因为它们是设置页面内容的不同方式。如果你使用 template,你可以直接使用 JSX 语法将任何类型的值绑定到 props 等。如果你使用 html,它必须是一个包含你的 html 内容的字符串页面,在这种情况下,您只能将字符串值绑定到 props。

如果您想在示例中使用 html,则需要

const page = newSpecPage({
  components: [MyBadge],
  html: `<my-badge skin="secondary"></my-badge>`,
});

我认为您不能在这种情况下使用自关闭语法,因为它对自定义元素无效,请参阅 this answer