模板组件的Jest测试不适用于变量

问题描述

我想测试模板组件并在测试中配置全局变量,如下所示:

describe('my-component',() => {
  const myVarMock = 1;

  let page;
  let shadowRoot: ShadowRoot;

  beforeEach(async () => {
    page = await newSpecPage({
      components: [MyComponent],html: `<my-component></my-component>`,supportsShadowDom: true,autoApplyChanges: true
    });
    shadowRoot = page.root.shadowRoot;
  });


  it('should test',() => {
    page.rootInstance.myVar= myVarMock;
    page.rootInstance.componentwillLoad();
    page.rootInstance.render();

    console.log(shadowRoot.innerHTML.toString());
    const buttonElement = shadowRoot.querySelector('.my-button'); //is null because shadow root is empty
  });
});

设置myVar后,“我的组件”仅呈现某些内容。在我的测试的console.log中,shadowRoot始终为空,尽管我在测试中显式调用了render(),并且当我在调试模式下通过render函数时,它具有myVar的值并呈现所有内容。但是为什么shadowRoot然后为空,而我的buttonElement未定义?

组件:

@Component({
  tag: 'my-component',shadow: true,})
export class MyComponent{

  public myVar;

  componentwillLoad() {
    ...
  }

    render() {
        return (
          <Host>
            {this.myVar? (
                 <div class="my-button"></div>
             ): null}
          </Host>
        )
    }
}

解决方法

手动调用诸如componentWillLoadrender之类的生命周期钩子并不能满足我的期望。 Stencil运行时调用render并使用返回值(JSX)最终呈现您的组件。手动调用render不会渲染或重新渲染组件。实际上,除了向您返回一些JSX之外,它什么都不做,但是您对返回值不做任何事情。

我认为您遇到的主要问题是myVar装饰器未将@Prop()声明为属性。因此,即使您已将班级成员标记为public并能够从外部进行更改,Stencil也不会为您提供有关该道具的任何信息。参见https://stenciljs.com/docs/properties

相反,您必须将其定义为:

@Prop() myVar?: number;

这样,它将在每次更新道具的值时使模板重新渲染组件。

您的测试用例应该看起来像

it('should test',() => {
    page.root.myVar = myVarMock;

    console.log(shadowRoot.innerHTML.toString());
    const buttonElement = shadowRoot.querySelector('.my-button');

    expect(buttonElement).not.toBeNull();
});