Skip to content

Commit

Permalink
docs(storybook): add documentation about storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
sipayRT committed Sep 13, 2024
1 parent b41127a commit 5f042a1
Show file tree
Hide file tree
Showing 4 changed files with 344 additions and 0 deletions.
26 changes: 26 additions & 0 deletions blog/storybook-testing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Скриншотное тестирование со Storybook
slug: screenshot-testing-with-storybook
hide_table_of_contents: false
date: 2024-09-11T13:00
---

[Storybook][storybook] - это инструмент для разработки пользовательских интерфейсов на основе компонентов. Он позволяет разработчикам независимо визуализировать компоненты в различных состояниях в изолированной от остальных компонентов среде.
Такой "шоурум" идеально подходит для скриншотного тестирования ваших компонентов, т.к. за счет этой изолированной среды такие тесты получаются в разы стабильнее и быстрее, чем вариант с e2e.

С помощью плагина [@testplane/storybook][testplane-storybook] предоставляется возможность автоматически проверять изменения ваших компонентов с помощью скриншотного тестирования без единой строчки кода теста.
Вам достаточно описать ваш компонент в `Storybook`, а `testplane` при запуске автоматически сгенерит все необходимые тесты, прогонит их в нужных браузерах и предоставит визуальный отчет для обновления скриншотов.
При этом, если для компонентов была задекларирована [play-функция][play-function], то `testplane` перед началом теста выполнит ее, чтобы привести компонент в нужное состояние.

Но если и этих возможностей вам не хватит, то вы можете прямо в story-файле описать testplane-тест, который будет выполнен как дополнительный тест для компонента.

### Как использовать?

Узнайте больше об этом в нашей документации <a href="/docs/v8/visual-testing/with-storybook">Скриншотное тестирование со Storybook</a>.

[Пример проекта][example] с настроенным скриншотным тестированием со Storybook можно посмотреть в нашем репозитории на GitHub.

[storybook][https://storybook.js.org]
[testplane-storybook][https://github.com/gemini-testing/testplane-storybook]
[play-function][https://storybook.js.org/docs/writing-stories/play-function]
[example]: https://github.com/gemini-testing/testplane/examples/storybook-autoscreenshots
56 changes: 56 additions & 0 deletions docs/visual-testing/visual-testing-intro.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Визуальное тестирование

В testplane реализовано визуальное тестирование, с помощью которого пользователь может проверить визуальные изменения отдельного компонента, вьюпорта или всей страницы целиком.
Для анализа тестов, сохранения/обновления измененных изображений и запуска тестов рекомендуется использовать плагин [html-reporter][html-reporter], который предоставляет удобный UI для всех действий.

### Особенности сравнения скриншотов

При вызове команды `assertView` осуществляется поиск нужного элемента на странице с его автоматическим ожиданием. По умолчанию перед снятием скриншота на странице будет отключена анимация, чтобы исключить в будущем нестабильность теста из-за изменяющегося состояния элемента.

При сравнении учитываются следующие настройки:

- мигающая каретка в текстовых инпутах игнорируется по умолчанию
- на изображении игнорируются элементы, которые были указаны в опциях сравнения
- учитываются настройки точности сравнения (допустимые отклонения)
- учитываются настройки точности сравнения антиалиасинга для шрифтов (самый частый дифф на скриншотах)

### Использование

```typescript
await browser.assertView(state, options);
await browser.assertView(state, selector, options);
await element.assertView(state, options);
```

Команда `assertView` доступна как в контексте браузера, так и в контексте найденного элемента. Набор аргументов при этом отличается:

```typescript
it("check search view", async ({ browser }) => {
// ...

// taking screenshot of the current viewport
await browser.assertView("viewport-screen");

// taking screenshot of a specific element (from the browser context)
await browser.assertView("any-state-name", ".DocSearch", opts);

const searchInput = await browser.$(".DocSearch");
await searchInput.click();

// taking screenshot of a previously found item (from the element context)
await searchInput.assertView("any-state-name");
});
```

Подробнее о возможностях команды `assertView` читайте в соответствующих разделах.

### Связанные команды

- [browser.assertView][browser-command]
- [element.assertView][element-command]

[html-reporter]: ../../html-reporter/html-reporter-setup

[looks-same]: [https://github.com/gemini-testing/looks-same]
[browser-command]: https://testplane.io/docs/v8/commands/browser/assertView/
[element-command]: https://testplane.io/docs/v8/commands/element/assertView/
256 changes: 256 additions & 0 deletions docs/visual-testing/with-storybook.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
import Admonition from "@theme/Admonition";

# Скриншотное тестирование со Storybook

[Storybook][storybook] - это инструмент для разработки пользовательских интерфейсов на основе компонентов. Он позволяет разработчикам независимо визуализировать компоненты в различных состояниях в изолированной от остальных компонентов среде.
Такой "шоурум" идеально подходит для скриншотного тестирования ваших компонентов, т.к. за счет этой изолированной среды такие тесты получаются в разы стабильнее и быстрее, чем вариант с e2e.

С помощью плагина [@testplane/storybook][testplane-storybook] предоставляется возможность автоматически проверять изменения ваших компонентов с помощью скриншотного тестирования.
Вам достаточно описать ваш компонент в `Storybook`, а `testplane` при запуске автоматически сгенерит все необходимые тесты, прогонит их в нужных браузерах и предоставит визуальный отчет для обновления скриншотов.

## Как использовать? {#how_to_use}

### Шаг 1: Установка необходимых зависимостей

Если в Вашем проекте еще нет `Testplane`, то рекомендуем ознакомиться с разделом [quickstart][quickstart] или выполнить в директории Вашего проекта команду ниже:

```bash
npm init testplane@latest
```

Устанавливаем плагин для `testplane`

```bash
npm install @testplane/storybook --save-dev
```

### Шаг 2: Настройка плагина

Для работы плагина достаточно минимальной настройки - нужно просто объявить его в конфиге `testplane` без дополнительных опций:

```typescript
// .testplane.conf.ts
export default {
plugins: {
"@testplane/storybook": {},

// other Testplane plugins...
},

// other Testplane settings...
};
```

### Шаг 3: Запуск тестов

Для запуска storybook-тестов необходимо добавить опцию `--storybook`. Опция `--update-refs` позволяет сохранить/обновить эталонные изображения через CLI:

```bash
npx testplane --storybook --update-refs
```

С помощью GUI-режима вы можете визуально оценить изменения в скриншотах, обновить их или перезапустить тесты:

```bash
npx testplane gui --storybook
```

Если в Вашем проекте используется Storybook версии 6.x, то в настройках Storybook необходимо включить сохранение json-файла с Вашими историями:

```typescript
// .storybook/main.js
export default {
// ...
features: {
// ...
buildStoriesJson: true,
},
};
```

## Кастомные тесты {#custom_tests}

Некоторые компоненты перед скриншотом нужно привести в какое-либо состояние. Для этого у сторибука есть сущность под названием [play-функция][play-function]. Если она определена, мы сначала выполним все action-ы из нее, и только после этого сделаем скриншот.
Если вам не хватает выразительности Storybook, то вы можете в самой "Истории" описать testplane-тест, который будет выполнен как дополнительный тест для компонента.

```typescript
// stories/Primary.stories.ts
import type { StoryObj } from "@storybook/react";
import type { WithTestplane } from "@testplane/storybook";

export const Primary: WithTestplane<StoryObj> = {
args: {
primary: true,
label: "Button",
},
testplane: {
"my test": async ({ browser, expect }) => {
const element = await browser.$(".storybook-button");

await expect(element).toHaveText("Button");
},
},
};
```

Также для теста можно добавить дополнительные настройки

```typescript
// stories/Primary.stories.ts
import type { WithTestplane } from "@testplane/storybook";
import type { Meta, StoryObj } from "@storybook/react";

const meta: WithTestplane<Meta<typeof Button>> = {
title: "Example/Button",
component: Button,
testplane: {
skip: false, // if true, skips all Testplane tests from this story file
autoscreenshotSelector: ".my-selector", // Custom selector to auto-screenshot elements
browserIds: ["chrome"], // Testplane browsers to run tests from this story file
assertViewOpts: {
// override default assertView options for tests from this file
ignoreDiffPixelCount: 5,
},
},
};

export default meta;
```

<Admonition type="warning">
При добавлении testplane-тестов расширение Ваших story-файлов должно быть `.js` или `.ts`.
</Admonition>

## Параметры конфигурации плагина

<table>
<thead>
<tr>
<td>**Параметр**</td>
<td>**Тип**</td>
<td>**По&nbsp;умолчанию**</td>
<td>**Описание**</td>
</tr>
</thead>
<tbody>
<tr>
<td>enabled</td>
<td>`Boolean`</td>
<td>true</td>
<td>Включить / отключить плагин.</td>
</tr>
<tr>
<td>storybookConfigDir</td>
<td>`String`</td>
<td>".storybook"</td>
<td>Путь к директории конфигурационного файла Storybook.</td>
</tr>
<tr>
<td>autoScreenshots</td>
<td>`Boolean`</td>
<td>true</td>
<td>Включить / отключить авто матическое скриншотное тестирование (будут выполняться только вручную описанные tetplane-тесты)</td>
</tr>
<tr>
<td>localport</td>
<td>`Number`</td>
<td>6006</td>
<td>Порт для запуска dev-сервера Storybook.</td>
</tr>
<tr>
<td>remoteStorybookUrl</td>
<td>`String`</td>
<td>""</td>
<td>Урл удаленного Storybook. Если указан, то локальный dev-сервер Storybook не будет запущен.</td>
</tr>
<tr>
<td>browserIds</td>
<td>`Array<String | RegExp>`</td>
<td>[]</td>
<td>Массив id браузеров, в которых будут запущены тесты. По умолчанию тесты будут запущены во всех браузерах, описанных в конфиге testplane</td>
</tr>
</tbody>
</table>

Например, для запуска тестов на Storybook, опубликованном удаленно на `s3`, настройка будет выглядеть следующим образом:

```typescript
// .testplane.conf.ts
export default {
plugins: {
"@testplane/storybook": {
remoteStorybookUrl: "https://yastatic.net/s3/storybook/index.html",
},

// other Testplane plugins...
},

// other Testplane settings...
};
```

## Дополнительные настройки {#extra_config}

В Вашем проекте уже могут быть настроены другие типы тестирования, запускающиеся с помощью `testplane`. Чтобы не смешивать сущности, мы рекомендуем для storybook-тестов использовать отдельный конфиг и указывать его при запуске тестов.

```bash
npx testplane --storybook --config .testplane.storybook.conf.ts
```

Сокращенная версия запуска

```bash
npx testplane --storybook -c .testplane.storybook.conf.ts
```

Отдельный конфиг позволит Вам описать хранение скриншотов сторибуков рядом с Вашим story-файлом:

```typescript
// .testplane.storybook.conf.ts
import path from "path";
import { getStoryFile } from "@testplane/storybook";

export default {
screenshotsDir: test => {
const relativeStoryFilePath = getStoryFile(test);
const relativeStoryFileDirPath = path.dirname(relativeStoryFilePath);

return path.join(relativeStoryFileDirPath, "screens", test.id, test.browserId);
},
// other Testplane settings...
};
```

В данном примере эталонные скриншоты будут сохранены в директории `screens/<testId>/<browserId>` относительно директории Вашего story-файла.

## Оптимизация запуска тестов {#optimize_run}

Storybook-тесты сами по себе довольно быстрые, т.к. для них не нужно сложное окружение, а на странице рендерится только один компонент.
В контексте браузера 1 раз создается окружения для тестирования Storybook и переиспользуется от теста к тесту. Поэтому, для максимальной скорости прохождения тестов мы рекомендуем выставлять опцию [testsPerSession][tests-per-session] со значением не меньше 20, чтобы переиспользовать браузерную сессию как можно дольше:

```typescript
// .testplane.storybook.conf.ts
export default {
testsPerSession: 40, // set value for all browsers

browsers: {
"chrome-desktop": {
testsPerSession: 50, // or set value for current browser
},
firefox: {
// ...
},
},

// other Testplane settings...
};
```

Также, для storybook-тестов будет проигнорирована опция [isolation][isolation], чтобы не пресоздавать окружение на каджый тест (это никак не влияет на стабильность тестов).

[quickstart]: ../../quickstart
[tests-per-session]: ../../config/browsers/#tests_per_session
[isolation]: ../../config/browsers/#isolation
[storybook]: https://storybook.js.org
[testplane-storybook]: https://github.com/gemini-testing/testplane-storybook
[play-function]: https://storybook.js.org/docs/writing-stories/play-function
6 changes: 6 additions & 0 deletions sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ const sidebars: SidebarsConfig = {
items: [{ type: "autogenerated", dirName: "config" }],
link: { type: "doc", id: "config/main" },
},
{
type: "category",
label: "Visual testing",
items: [{ type: "autogenerated", dirName: "visual-testing" }],
link: { type: "doc", id: "visual-testing/visual-testing-intro" },
},
{
type: "category",
label: "Guides",
Expand Down

0 comments on commit 5f042a1

Please sign in to comment.