问题描述
我想测试模板组件并在测试中配置全局变量,如下所示:
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>
)
}
}
解决方法
手动调用诸如componentWillLoad
和render
之类的生命周期钩子并不能满足我的期望。 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();
});