title: Trying to mock Stenciljs store (@stencil/store) state (multiple times) while writing unit test for Web Components
body: <p>I am working on writing Unit Tests for Web Components. These Web Components are built using <a href="https://stenciljs.com/" rel="nofollow noreferrer">Stenciljs</a>. StencilJS uses Jest for defining and running these unit tests. Also, I am new to Jest and StencilJS, so my methods may not be as per some defined standards. Let me describe the application and my problem.</p>
  
  <p>The project has a global state defined in a file using <a href="https://stenciljs.com/docs/stencil-store" rel="nofollow noreferrer">Stencil-Store</a>. The content of the file looks like this:</p>
  
  <p><code>global/store.ts</code></p>
  
  <pre><code>
      import { createStore } from '@stencil/store';
  
        const { state } = createStore({
          appName: 'Application Name',
          platformName: 'Platform Name',
          mode: 'default', // light, dark, default
          appActionBar: 'closed', // open, closed 
        });
  
      export default state;
  
  </code></pre>
  
  <p>So in any component where we need information from the state or if the component needs to update information in the state, we import this <code>state</code> in that component and perform any action. For example, consider a Web Component <code>app-shell</code></p>
  
  <p><code>app.shell.tsx</code></p>
  
  <pre><code>
      import { Component, h, Host } from '@stencil/core';
      import state from './global/store';
  
      @Component({
        tag: 'app-shell',
        styleUrl: 'app-shell.scss',
        shadow: true,
      })
      export class AppShell {
      render() {
          return (
            &lt;Host
              data-mode={state.mode}
              class={{
                'action-bar-closed': state.appActionBar === 'closed',
                'action-bar-open': state.appActionBar === 'open',
              }}
            &gt;
              {/* Header */}
              &lt;div
                class={{
                  'app-shell-header': true,
                  'side-panel-open': state.sidepanel === true,
                }}
              &gt;
                &lt;slot name="app-shell-header"&gt;&lt;/slot&gt;
              &lt;/div&gt;
              {/* Shell Content */}
              &lt;div class="app-shell-content"&gt;
                &lt;slot name="app-shell-content"&gt;&lt;/slot&gt;
              &lt;/div&gt;
            &lt;/Host&gt;
      }
      }
  
  </code></pre>
  
  <p>As you can notice in above code that this web component reads values from the <code>state</code> and applies <code>classes</code> based on that. Now in order to test different classes getting applied, I thought it would a great idea to <code>mock the state</code> and provide different values of <code>states</code> for different tests.</p>
  
  <p>So with this in mind, I started writing test for this web component. I referred to <a href="https://stenciljs.com/docs/mocking" rel="nofollow noreferrer">mocking</a> doc from StencilJS and testing doc in general. Here is a <code>spec</code> file:</p>
  
  <p><code>app-shell.spec.ts</code></p>
  
  <pre><code>
      // Mock the global state for testing purposes.
      jest.mock('./global/store', () =&gt; {
        const { state } = createStore({
          appName: 'Mocked Name',
          platformName: 'Mocked Platform Name',
          mode: 'default',
          appActionBar: 'closed',
        });
        return state;
      });
      import { newSpecPage, SpecPage } from '@stencil/core/testing';
      import { createStore } from '@stencil/store';
      import { AppShell } from './app-shell';
  
      describe('app-shell', () =&gt; {
        let page: SpecPage;
        let element: any;
        let componentInstance: any;
  
        beforeEach(async () =&gt; {
          page = await newSpecPage({
            components: [AppShell],
            html: `&lt;app-shell&gt;&lt;/app-shell&gt;`,
            supportsShadowDom: true,
          });
          element = page.doc.querySelector('app-shell');
          componentInstance = page.rootInstance;
        });
        describe('build and render', () =&gt; {
          it('should build', async () =&gt; {
            expect(page).toBeTruthy();
          });
          it('should render', async () =&gt; {
            expect(page.root).toEqualHtml(`
            &lt;app-shell class="action-bar-closed" data-mode="default"&gt;
              &lt;mock:shadow-root&gt;
                &lt;div class="app-shell-header"&gt;
                  &lt;slot name="app-shell-header"&gt;&lt;/slot&gt;
                &lt;/div&gt;
                &lt;div class="app-shell-content"&gt;
                  &lt;slot name="app-shell-content"&gt;&lt;/slot&gt;
                &lt;/div&gt;
              &lt;/mock:shadow-root&gt;
            &lt;/app-shell&gt;
          `);
          });
        });
      })
  
  ;
  </code></pre>
  
  <p>So by following the StencilJS mocking documentation, I was able to mock the state value (as seen in above spec file) using <code>jest.mock()</code>. So when I run this test, I get the mocked state values as defined in this spec file. All good!</p>
  
  <p><strong>Problem</strong></p>
  
  <p>However, I wanted to <strong>override/update</strong> the mocked state values for different <code>describe</code> under the same <code>spec</code> file so that I can provide <code>different</code> state values to test separate cases.</p>
  
  <p>So for example, I want to achieve something like this.</p>
  
  <pre><code>
  
  // Mock the global state for testing purposes.
      jest.mock('./global/store', () =&gt; {
        const { state } = createStore({
          appName: 'Mocked Name',
          platformName: 'Mocked Platform Name',
          mode: 'default',
          appActionBar: 'closed',
        });
        return state;
      });
      import { newSpecPage, SpecPage } from '@stencil/core/testing';
      import { createStore } from '@stencil/store';
      import { AppShell } from './app-shell';
  
      describe('app-shell', () =&gt; {
        let page: SpecPage;
        let element: any;
        let componentInstance: any;
  
        beforeEach(async () =&gt; {
          page = await newSpecPage({
            components: [AppShell],
            html: `&lt;app-shell&gt;&lt;/app-shell&gt;`,
            supportsShadowDom: true,
          });
          element = page.doc.querySelector('app-shell');
          componentInstance = page.rootInstance;
        });
        describe('build and render', () =&gt; {
          it('should build', async () =&gt; {
            expect(page).toBeTruthy();
          });
          it('should render', async () =&gt; {
            expect(page.root).toEqualHtml(`
            &lt;app-shell class="action-bar-closed" data-mode="default"&gt;
              &lt;mock:shadow-root&gt;
                &lt;div class="app-shell-header"&gt;
                  &lt;slot name="app-shell-header"&gt;&lt;/slot&gt;
                &lt;/div&gt;
                &lt;div class="app-shell-content"&gt;
                  &lt;slot name="app-shell-content"&gt;&lt;/slot&gt;
                &lt;/div&gt;
              &lt;/mock:shadow-root&gt;
            &lt;/app-shell&gt;
          `);
          });
        });
        describe('mock state again', () =&gt; {
          it('should have new mocked values', async () =&gt; {
             // Mock the global state for testing purposes.
             jest.mock('./global/store', () =&gt; {
             const { state } = createStore({
               appName: 'Mocked Name',
               platformName: 'Mocked Platform Name',
               mode: 'dark',
               appActionBar: 'open',
           });
        return state;
      });
            // Have expect statement here... 
          });
        });
      })
  ;
  
  </code></pre>
  
  <p>As you would notice in the above code snippet, I am trying to <code>mock</code> the <code>state</code> twice using <code>jest.mock()</code>. However, I am not able to mock the state again.</p>
  
  <p><strong>Question</strong>
  What is the correct way to solve my issue i.e. able to mock state multiple times in a single spec file?</p>
  
  <p>Any input would be appreciated. Thanks!</p>