'Stencil unit testing: How to mock initial state and load newSpecPage?

I am new to unit testing and planning to write unit test cases but not E-2-E for the below mentioned scenario and playgrounnd link for scenario is at the bottom.

Scenario:-

I have a @State variable called "ifSuccessResponse" with initial value set as false.

When @State variable "ifSuccessResponse" is true, green-div loads.

When @State variable "ifSuccessResponse" is false, red-div loads.

  1. How to mock initial state to have @State variable ifSuccessResponse to have value set as true and then load the newSpecPage so that I can test green-div is loaded.
  1. Is it possible to update the @State variable ifSuccessResponse after loading the page in Moc Doc using newSpecPage . Curious to know whether we can do this like how we can do in enzyme library using setState method.

Playground-link: https://webcomponents.dev/edit/Cbr1NS2QTrvC5scsmFZQ/src/index.stories.tsx



Solution 1:[1]

Instead of trying to mock State directly (by definition it is internal to component, otherwise you would/should use @Prop), you should find a way to get into the logic that exercise setting that state. Looking at the variable name, your component probably make call to some underlying API or service? If so, I would strongly recommend you to mock request/response to that service and then manipulate the State that way.

I use "fetch-mock" (https://www.npmjs.com/package/fetch-mock) to do this.

When you are using newSpecPage, you are dealing with DOM element so at that level, you want to minimize exposing internal logic like that so that you are actually testing how component is used. If you have complex logic, you could easily write unit test to test such function as well.

Solution 2:[2]

After creating the newSpecPage, you can access its contents. Try writing some console logs in your tests to see what you are working with.

For example:

console.log(page.root);
console.log(page.rootInstance);
console.log(page.root.outerHTML);

If you want to access or change a @State(), you can do that as follows

page.rootInstance.ifSuccessResponse = true

So the full test will look as follows

it('should show the green state', async () => {
  const page = await newSpecPage({
    components: [MyParentComponent],
    template: () => <my-parent-component></my-parent-component>,
  });

  page.rootInstance.ifSuccessResponse = true;

  const divEl = page.root.shadowRoot.querySelector('#green-div');
  expect(divEl.innerHTML).toEqual('My favorite color is green');
});

Unfortunately I'm not able to run your playground project, so I hope I did it correctly. I also edited your test name slightly to make it a readable sentence. I would advise you to name your tests likewise.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tomokat
Solution 2 richardec