Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 1 addition & 133 deletions blog/component-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,139 +38,7 @@ import Admonition from "@theme/Admonition";

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

Будем настраивать тестирование react-компонентов, написанных на TypeScript. Поэтому, для начала установим необходимые зависимости:

```bash
npm i testplane vite @vitejs/plugin-react @testing-library/react --save-dev
npm i react --save
```

Создаем Vite конфиг, в котором подключим плагин для поддержки React. Пример:

```javascript
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
});
```

Теперь настроим запуск тестов в браузере. Для этого укажем опцию [testRunEnv](https://github.com/gemini-testing/testplane/blob/master/docs/config.md#testrunenv). Пример:

```javascript
// .testplane.conf.ts
export const {
// ...
system: {
// ...
testRunEnv: ['browser', { viteConfig: './vite.config.ts' }],
},
sets: {
linux: {
files: [
'src/tests/**/*.testplane.tsx'
],
browsers: [
'chrome'
]
},
},
}
```

После чего можем написать тест, в котором просто выведем значение `document` в консоль без использования команды [browser.execute](/docs/v8/commands/browser/execute):

```javascript
// src/tests/test.testplane.tsx
it("should log document", async () => {
console.log(document);
});
```

Если бы такой тест выполнялся в окружении Node.js, то он бы упал с ошибкой `ReferenceError: document is not defined`. Но в нашем случае он будет выполнен прямо в браузере, где доступна глобальная переменная `document`. Поэтому, в логе браузера и терминала (про эту возможность расскажем ниже) мы увидим следующее:

```
{
location: {
ancestorOrigins: {},
href: 'http://localhost:56292/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
origin: 'http://localhost:56292',
protocol: 'http:',
host: 'localhost:56292',
hostname: 'localhost',
port: '56292',
pathname: '/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
search: '',
hash: ''
}
}
```

Напишем более сложный тест с рендерингом React-компонента. Для этого сначала напишем небольшой компонент:

```javascript
// src/components/Component.tsx
import { useState } from "react";

// Простой компонент с тайтлом и кнопкой-счетчиком
function Component() {
const [count, setCount] = useState(0);

return (
<div id="root">
<h1>Testplane Component Testing!</h1>
<button onClick={() => setCount(count => count + 1)}>count is {count}</button>
</div>
);
}

export default Component;
```

И напишем сам тест, который будет тестировать наш React-компонент:

```javascript
// src/tests/test.testplane.tsx
import { render } from "@testing-library/react";
import Component from "../components/Component";

it("should render react button", async ({ browser }) => {
render(<Component />); // рендерим компонент на сгенеренной странице Vite

const button = await browser.$("button");

await button.click();
await button.click();

await expect(button).toHaveText("count is 2");
});
```

С полноценно работающими примерами можно ознакомиться [здесь](https://github.com/gemini-testing/testplane/tree/master/examples/component-testing).

<Admonition type="warning" title="На данный момент есть ограничения">
- поддерживаются только компоненты, написанные на React в файлах `.jsx` и `.tsx`. Поддержка Vue
также есть в планах; - нет доступа к `currentTest` из хуков и теста; - временно не
поддерживается плагин @testplane/global-hook.
</Admonition>

### Какие дополнительные возможности поддерживаются?

#### 1. Hot Module Replacement (HMR)

В Vite поддерживается [HMR](https://vitejs.dev/guide/api-hmr.html). Это означает, что если изменить загруженный файл, то произойдет или ремаунт компонента, или полная перезагрузка страницы. В случае, если компонент описан в отдельном файле (т.е. не в одном файле с тестом), то будет выполнен ремаунт, но тест перезапущен не будет. А если изменить файл с тестом, то произойдет перезагрузка страницы, которая приведет к тому, что Testplane прервет выполнение текущего теста и запустит его заново. За счет такой возможности в Vite можно очень быстро разрабатывать компоненты и писать для них тесты. Рекомендуется использовать вместе с REPL-режимом.

При изменении исходников компонента не происходит полного перезапуска теста (маунтится по новой только сам компонент). При этом, если изменить код теста, то происходит полный перезапуск.

#### 2. Использование инстанса browser и expect прямо в DevTools браузера

В консоли браузера, в котором выполняется тест, доступны инстанс самого `browser` и инстанс `expect`. Это довольно удобно использовать при дебаге теста.

#### 3. Логи из консоли браузера в терминале

Вызов команд `log`, `info`, `warn`, `error`, `debug` и `table` на объекте `console` в браузере приводят к тому, что отображается информация не только в DevTools браузера, но также и в терминале, из которого был запущен Testplane. Т.е. можно вызвать `console.log` в тесте/компоненте и затем увидеть результат его выполнения в терминале. Это также довольно удобно при дебаге теста.
Узнайте больше об этом в нашей документации <a href="/docs/v8/guides/component-testing">Компонентное тестирование</a>.

### Заключение

Expand Down
1 change: 1 addition & 0 deletions docs/config/system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import TestRunEnvExample from "@site/docs/config/_partials/examples/_system-test
<tr><td>[`diffColor`](#diff_color)</td><td>`string`</td><td>`"#ff00ff"`</td><td>Цвет, которым нужно отображать дифф на скриншотах.</td></tr>
<tr><td>[`parallelLimit`](#parallel_limit)</td><td>`number`</td><td>`1`</td><td>Максимальное количество браузеров, которые могут быть запущены одновременно.</td></tr>
<tr><td>[`fileExtensions`](#file_extensions)</td><td>`string[]`</td><td>`[".js", ".mjs", ".ts", ".mts", ".jsx", ".tsx"]`</td><td>Расширения файлов, в которых Testplane будет искать тесты для запуска.</td></tr>
<tr><td>[`testRunEnv`](#testrunenv)</td><td>`nodejs` или `browser` или `Array`</td><td>`nodejs`</td><td>Возможно указать в каком окружении должны выполняться тесты.</td></tr>
</tbody>
</table>

Expand Down
168 changes: 168 additions & 0 deletions docs/guides/component-testing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import Admonition from "@theme/Admonition";

# Компонентное тестирование (экспериментальное)

## Введение

Узнайте больше об этом в посте про <a href="/blog/component-testing-intro">Компонентное тестирование</a> в нашем блоге.

## Пример

```typescript
import { render } from '@testing-library/react';
import Component from '../Component';

it('should render react component', async ({browser}) => {
// Отрендерить компонент на изолированной странице
render(<Component />);

// Найти кнопку внутри компонента и кликнуть по ней
const button = await browser.$("button");
await button.click();

// Проверить, что текст кнопки имеет ожидаемое значение
await expect(button).toHaveText("count is 1");
});
```

## Как начать?

Давайте настроим тестирование реакт компонентов, написанных на Typescript.

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

```bash
npm init testplane@latest
npm i vite @vitejs/plugin-react @testing-library/react --save-dev
npm i react --save
```

### Шаг 2: Создание конфигурации Vite и подключение плагина react

```typescript title="vite.config.ts"
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
});
```

### Шаг 3: Настройка запуска тестов в браузере (используя опцию testRunEnv)

```typescript title=".testplane.conf.ts"
export default {
// ...
system: {
// ...
testRunEnv: ["browser", { viteConfig: "./vite.config.ts" }],
},
sets: {
linux: {
files: ["src/tests/**/*.testplane.tsx"],
browsers: ["chrome"],
},
},
};
```

### Шаг 4: Написание теста

Чтобы проверить правильную конфигурацию, мы можем написать самый простой тест, в котором выводим значение document в консоль без использования команды [browser.execute][browser-execute]:

```typescript title="src/tests/test.testplane.tsx"
it("should log document", async () => {
console.log(document);
});
```

Если бы такой тест был выполнен в среде Node.js, то он упал бы с ошибкой: `ReferenceError: document is not defined`. Но в нашем случае он будет выполнен непосредственно в браузере, где глобальная переменная `document` доступна. Поэтому в консоли браузера и терминала мы увидим следующее:

```
{
location: {
ancestorOrigins: {},
href: 'http://localhost:56292/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
origin: 'http://localhost:56292',
protocol: 'http:',
host: 'localhost:56292',
hostname: 'localhost',
port: '56292',
pathname: '/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
search: '',
hash: ''
}
}
```

Давайте напишем более сложный тест с рендером компонента:

```typescript title="src/tests/test.testplane.tsx"
import { render } from '@testing-library/react';
import Component from '../Component';

it('should render react component', async ({browser}) => {
// Отрендерить компонент на изолированной странице
render(<Component />);

// Найти кнопку внутри компонента и кликнуть по ней
const button = await browser.$("button");
await button.click();

// Проверить, что текст кнопки имеет ожидаемое значение
await expect(button).toHaveText("count is 1");
});
```

И исходный код самого компонента:

```typescript title="src/Component.tsx"
import { useState } from 'react';

// A simple component with a title and a counter button
function Component() {
const [count, setCount] = useState(0);

return (
<div id="root">
<h1>Testplane Component Testing</h1>
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
);
}
```

Полностью работающие примеры можно найти [здесь][testplane-examples-component-testing].

## Временные ограничения

<Admonition type="warning">
* поддерживаются только компоненты, написанные на React в файлах .jsx и .tsx. Возможность
написания тестов в файлах .js будет реализована в ближайшем будущем. Мы также планируем
поддержку фреймворка Vue; * нет доступа к currentTest из it, beforeEach и afterEach. Это будет
добавлено в ближайшем будущем; * плагин [@testplane/global-hook][testplane-global-hook] в
настоящее время временно не поддерживается.
</Admonition>

## Дополнительные возможности

### Горячая замена модулей (HMR)

[HMR][vite-hmr] поддерживается в Vite. Это означает, что если вы измените загруженный файл, либо компонент будет повторно монтироваться, либо страница будет полностью предварительно загружена. Если компонент описан в отдельном файле (т.е. не в том же файле, что и тест), произойдет повторная установка, но тест не будет перезапущен. А если вы измените файл теста, страница будет перезагружена, что заставит Testplane прервать выполнение текущего теста и запустить его заново. Благодаря этой функции вы можете быстро разрабатывать компоненты в Vite и писать для них тесты. Рекомендуется использовать ее вместе с [REPL режимом][repl-mode].

### Использование экземпляров browser и expect напрямую в средствах разработчика браузера

Инстансы `browser` и `expect` доступны в глобальной области видимости браузера. Это довольно удобно использовать при отладке теста.

### Логи из консоли браузера в терминале

Вызов команд `log`, `info`, `warn`, `error`, `debug` и `table` на объекте `console` в браузере приводит к отображению информации не только в средствах разработчика браузера, но также в терминале, из которого был запущен Testplane. То есть, вы можете вызывать `console.log` в тесте/компоненте и увидеть результат его выполнения в терминале. Это особенно удобно при отладке тестов.

[test-run-env-option]: ../config/system.mdx#testrunenv
[browser-execute]: ../commands/browser/execute.mdx
[testplane-examples-component-testing]: https://github.com/gemini-testing/testplane/tree/master/examples/component-testing
[testplane-global-hook]: https://github.com/gemini-testing/testplane-global-hook
[vite-hmr]: https://vitejs.dev/guide/api-hmr.html
[repl-mode]: ../command-line/index.mdx#repl
Loading