Я работаю над написанием модульных тестов для веб-компонентов. Эти веб-компоненты созданы с использованием Stenciljs. StencilJS использует Jest для определения и запуска этих модульных тестов. Кроме того, я новичок в Jest и StencilJS, поэтому мои методы могут не соответствовать определенным стандартам. Позвольте мне описать приложение и мою проблему.
Глобальное состояние проекта определено в файле с помощью Stencil-Store. Содержимое файла выглядит так:
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
в этот компонент и выполняем любое действие. Например, рассмотрим веб-компонент 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>
}
}
Как вы можете заметить в приведенном выше коде, этот веб-компонент считывает значения из state
и применяет classes
на основе этого. Теперь, чтобы протестировать применение различных классов, я подумал, что было бы неплохо mock the state
и предоставить разные значения states
для разных тестов.
Помня об этом, я начал писать тест для этого веб-компонента. Я сослался на издевательский документ из 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()
. Поэтому, когда я запускаю этот тест, я получаю фиктивные значения состояния, как определено в этом файле спецификации. Все хорошо!
Проблема
Однако я хотел переопределить / обновить фиктивные значения состояния для разных describe
в одном и том же spec
файле, чтобы я мог предоставить 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
дважды, используя jest.mock()
. Однако я не могу снова издеваться над государством.
Вопрос Каков правильный способ решения моей проблемы, т. е. возможность многократно имитировать состояние в одном файле спецификации?
Любой вклад будет оценен. Спасибо!