Reputation: 3489
I want to test a stencil component and configure a global variable in my test like this:
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
});
});
My Component only renders something, when myVar is set. In the console.log of my test, shadowRoot is always empty, although I explicitly call render() in the test and when I go through the render function in debug-mode it has a value for myVar and renders everything. But why is shadowRoot then empty and my buttonElement is undefined?
Component:
@Component({
tag: 'my-component',
shadow: true,
})
export class MyComponent{
public myVar;
componentWillLoad() {
...
}
render() {
return (
<Host>
{this.myVar? (
<div class="my-button"></div>
): null}
</Host>
)
}
}
Upvotes: 3
Views: 2227
Reputation: 4978
Calling those life-cycle hooks like componentWillLoad
and render
manually does not do what I think you're expecting it to do. The Stencil runtime calls render
and uses the return value (JSX) to eventually render your component. Manually calling render
does not render or re-render your component. In fact, it doesn't do anything except returning some JSX to you but you're not doing anything with the return value.
I think the main issue in your case is that myVar
is not declared as a property with the @Prop()
decorator. So even though you have marked your class member as public
and are able to change it from the outside, Stencil will not wire up anything for you regarding that prop. See https://stenciljs.com/docs/properties.
Instead, you'll have to define it as:
@Prop() myVar?: number;
That way it will cause Stencil to re-render your component every time you update the prop's value.
Your test case should just look like
it('should test', () => {
page.root.myVar = myVarMock;
console.log(shadowRoot.innerHTML.toString());
const buttonElement = shadowRoot.querySelector('.my-button');
expect(buttonElement).not.toBeNull();
});
Upvotes: 2