我正在为Web组件编写单元测试。这些Web组件是使用史坦奇斯构建的。StencilJS使用Jest来定义和运行这些单元测试。而且,我对Jest和StencilJS还很陌生,所以我的方法可能不符合某些定义的标准。让我描述一下应用程序和我的问题。
该项目在使用模版店的文件中定义了全局状态。文件的内容如下所示:
global/store.ts
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
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
// 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状态值来测试不同的情况。
举个例子,我想实现这样的目标。
// 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。但是,我不能再嘲笑这个国家了。
问题,解决我的问题的正确方法是什么,即能够在单个规范文件中多次模拟状态?
如有任何意见,将不胜感激。谢谢!
发布于 2020-06-05 03:04:10
让我在这里回答这个问题。
所以我在贴出这个问题链接后几分钟内就在StencilJS上得到了答案。
谢谢你@simon-h nisch
首先,您的不需要在所有上模拟存储,并且可以从Spec文件直接更新状态本身。
我不得不做几个改变:
1)因此,我将store.ts更改为随状态导出dispose()。
export const { state, dispose } = createStore({ ... })2)接下来,我将spec文件更新为如下所示:
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的许多新手(比如我)都有帮助:)
https://stackoverflow.com/questions/62165792
复制相似问题