首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在编写Web组件单元测试时,尝试模拟Stenciljs存储(@模具/存储)状态(多次)

在编写Web组件单元测试时,尝试模拟Stenciljs存储(@模具/存储)状态(多次)
EN

Stack Overflow用户
提问于 2020-06-03 05:26:43
回答 1查看 1.5K关注 0票数 1

我正在为Web组件编写单元测试。这些Web组件是使用史坦奇斯构建的。StencilJS使用Jest来定义和运行这些单元测试。而且,我对Jest和StencilJS还很陌生,所以我的方法可能不符合某些定义的标准。让我描述一下应用程序和我的问题。

该项目在使用模版店的文件中定义了全局状态。文件的内容如下所示:

global/store.ts

代码语言:javascript
复制
    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;

因此,在任何需要状态信息的组件中,或者如果组件需要更新状态中的信息,我们将在该组件中导入这个state并执行任何操作。例如,考虑一个Web组件app-shell

app.shell.tsx

代码语言:javascript
复制
    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 (
          <Host
            data-mode={state.mode}
            class={{
              'action-bar-closed': state.appActionBar === 'closed',
              'action-bar-open': state.appActionBar === 'open',
            }}
          >
            {/* Header */}
            <div
              class={{
                'app-shell-header': true,
                'side-panel-open': state.sidepanel === true,
              }}
            >
              <slot name="app-shell-header"></slot>
            </div>
            {/* Shell Content */}
            <div class="app-shell-content">
              <slot name="app-shell-content"></slot>
            </div>
          </Host>
    }
    }

正如您在上面的代码中所注意到的,这个web组件从state中读取值并在此基础上应用classes。现在,为了测试不同类的应用,我认为mock the state是一个很好的主意,并为不同的测试提供了不同的states值。

因此,考虑到这一点,我开始为这个web组件编写测试。我从StencilJS和一般的测试文档中引用了StencilJS文档。下面是一个spec文件:

app-shell.spec.ts

代码语言:javascript
复制
    // Mock the global state for testing purposes.
    jest.mock('./global/store', () => {
      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', () => {
      let page: SpecPage;
      let element: any;
      let componentInstance: any;

      beforeEach(async () => {
        page = await newSpecPage({
          components: [AppShell],
          html: `<app-shell></app-shell>`,
          supportsShadowDom: true,
        });
        element = page.doc.querySelector('app-shell');
        componentInstance = page.rootInstance;
      });
      describe('build and render', () => {
        it('should build', async () => {
          expect(page).toBeTruthy();
        });
        it('should render', async () => {
          expect(page.root).toEqualHtml(`
          <app-shell class="action-bar-closed" data-mode="default">
            <mock:shadow-root>
              <div class="app-shell-header">
                <slot name="app-shell-header"></slot>
              </div>
              <div class="app-shell-content">
                <slot name="app-shell-content"></slot>
              </div>
            </mock:shadow-root>
          </app-shell>
        `);
        });
      });
    })

;

因此,通过遵循StencilJS模拟文档,我能够使用jest.mock()模拟状态值(如上面的规范文件所示)。因此,当我运行这个测试时,我得到了这个规范文件中定义的模拟状态值。一切都好!

问题

但是,我希望在同一个override/update文件下为不同的describe提供模拟的状态值,以便能够提供different状态值来测试不同的情况。

举个例子,我想实现这样的目标。

代码语言:javascript
复制
// Mock the global state for testing purposes.
    jest.mock('./global/store', () => {
      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', () => {
      let page: SpecPage;
      let element: any;
      let componentInstance: any;

      beforeEach(async () => {
        page = await newSpecPage({
          components: [AppShell],
          html: `<app-shell></app-shell>`,
          supportsShadowDom: true,
        });
        element = page.doc.querySelector('app-shell');
        componentInstance = page.rootInstance;
      });
      describe('build and render', () => {
        it('should build', async () => {
          expect(page).toBeTruthy();
        });
        it('should render', async () => {
          expect(page.root).toEqualHtml(`
          <app-shell class="action-bar-closed" data-mode="default">
            <mock:shadow-root>
              <div class="app-shell-header">
                <slot name="app-shell-header"></slot>
              </div>
              <div class="app-shell-content">
                <slot name="app-shell-content"></slot>
              </div>
            </mock:shadow-root>
          </app-shell>
        `);
        });
      });
      describe('mock state again', () => {
        it('should have new mocked values', async () => {
           // Mock the global state for testing purposes.
           jest.mock('./global/store', () => {
           const { state } = createStore({
             appName: 'Mocked Name',
             platformName: 'Mocked Platform Name',
             mode: 'dark',
             appActionBar: 'open',
         });
      return state;
    });
          // Have expect statement here... 
        });
      });
    })
;

正如您在上面的代码片段中所注意到的,我正在尝试使用mock两次state。但是,我不能再嘲笑这个国家了。

问题,解决我的问题的正确方法是什么,即能够在单个规范文件中多次模拟状态?

如有任何意见,将不胜感激。谢谢!

EN

回答 1

Stack Overflow用户

发布于 2020-06-05 03:04:10

让我在这里回答这个问题。

所以我在贴出这个问题链接后几分钟内就在StencilJS上得到了答案。

谢谢你@simon-h nisch

首先,您的不需要在所有上模拟存储,并且可以从Spec文件直接更新状态本身。

我不得不做几个改变:

1)因此,我将store.ts更改为随状态导出dispose()

代码语言:javascript
复制
export const { state, dispose } = createStore({ ... })

2)接下来,我将spec文件更新为如下所示:

代码语言:javascript
复制
import {state, dispose} from '../global/store';

  beforeEach(async () => {
    dispose();
    page = await newSpecPage({
      components: [AppShell],
      html: `<app-shell></app-shell>`,
      supportsShadowDom: true,
    });
    element = page.doc.querySelector('app-shell');
    componentInstance = page.rootInstance;
  });

describe('my test', () => {
  it('light mode', async () => {
    // update state
    state.mode = 'light';
    // expect statement
    ...
  });
  it('dark mode', async () => {
    // update state
    store.mode = 'dark';
    // expect statement
    ...
  });
});

现在我完成了beforeEach中的所有设置,在创建page之前,我只需要调用dispose

通过以这种方式更新状态,我不需要模拟状态。

希望这对StencilJS的许多新手(比如我)都有帮助:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62165792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档