с частичным текстом "Документ" найден: ${isTagPartialLinkFound}`);
+
+ // Case-insensitive поиск с тегом div
+ const divCaseInsensitive = await browser.$('div.=testplane');
+ const isDivCaseInsensitiveFound = await divCaseInsensitive.isExisting();
+ console.log(`Элемент с case-insensitive текстом "testplane" найден: ${isDivCaseInsensitiveFound}`);
+ });
+});
+```
+
+Стоит использовать, если:
+
+- текст элементов стабилен;
+- вам необходимо, чтобы тест был максимально приближен к реальным пользовательским сценариям.
+
+
+### Shadow DOM селекторы
+
+Shadow DOM селекторы позволяют работать с элементами внутри Shadow DOM — инкапсулированной части DOM-дерева. Например, если у вас есть кастомный элемент `my-custom-element`, вы можете найти кнопку внутри его Shadow DOM с помощью `shadow$("button")`.
+
+```javascript
+// Простой доступ в Shadow DOM
+const customElement = await browser.$("my-custom-element");
+const button = await customElement.shadow$("button");
+await button.click();
+
+// Множественные элементы в Shadow DOM
+const slotElements = await customElement.shadow$$(".slot-item");
+```
+
+Стоит использовать, если:
+
+- работаете с Web Components и Custom Elements;
+- приложение использует Shadow DOM для инкапсуляции стилей;
+- тестируете компоненты из сторонних библиотек (Lit, Stencil, native Web Components);
+- нужен доступ к элементам внутри shadow root;
+- работаете с дизайн-системой на базе Web Components.
+
+## Testing-library
+
+Testing Library позволяет искать элементы так, как их ищут на странице пользователи — по тексту, типу элемента или другим атрибутам, которые не зависят от деталей вашей верстки.
+
+### ByRole
+
+`getByRole` — основной метод в Testing Library, который позволяет находить элементы по их ARIA-ролям. Например, если вы используете метод `screen.getByRole("button", { name: /submit/i })`, то найдете кнопку с текстом, содержащим `submit`.
+
+```javascript
+describe("getByRole", () => {
+ it("Поиск кнопки с помощью метода getByRole", async ({ browser }) => {
+ await browser.url("https://testplane.io/");
+
+ const button = await browser.getByRole("button", { name: "Get started" });
+
+ await button.click();
+ });
+});
+```
+
+### ByLabelText
+
+Для поиска элементов форм по тексту их меток (`label`), используйте метод `getByLabelText`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск по тексту label (полное совпадение)
+const emailInput = screen.getByLabelText("Email Address");
+await userEvent.type(emailInput, "user@example.com");
+
+// Поиск с регулярным выражением (частичное совпадение, case-insensitive)
+const passwordInput = screen.getByLabelText(/password/i);
+await userEvent.type(passwordInput, "secure123");
+```
+
+### ByPlaceholderText
+
+Чтобы найти поле ввода по тексту `placeholder`, используйте селектор `getByPlaceholderText`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск по placeholder
+const searchInput = screen.getByPlaceholderText("Search...");
+await userEvent.type(searchInput, "testing library");
+
+// С регулярным выражением
+const emailInput = screen.getByPlaceholderText(/enter.*email/i);
+await userEvent.type(emailInput, "test@example.com");
+```
+
+### ByText
+
+Чтобы найти текстовый элемент по его содержимому, используйте метод `getByText`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск по точному тексту
+const heading = screen.getByText("Welcome to our application");
+expect(heading).toBeInTheDocument();
+
+// С регулярным выражением (частичное совпадение)
+const errorMessage = screen.getByText(/error.*occurred/i);
+expect(errorMessage).toHaveClass("error");
+```
+
+### ByDisplayValue
+
+Для поиска элемента по их текущему значению, используйте метод `getByDisplayValue`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск input с конкретным значением
+const emailInput = screen.getByDisplayValue("user@example.com");
+expect(emailInput).toBeInTheDocument();
+
+// Поиск с регулярным выражением
+const searchInput = screen.getByDisplayValue(/search query/i);
+```
+
+### ByAltText
+
+Для поиска изображений по тексту `alt`, используйте метод `getByAltText`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск изображения по alt тексту
+const logo = screen.getByAltText("Company Logo");
+expect(logo).toBeInTheDocument();
+expect(logo).toHaveAttribute("src", "/images/logo.png");
+```
+
+### ByTitle
+
+Чтобы найти элемент по атрибуту title, используйте метод `getByTitle`.
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Поиск элемента по title атрибуту
+const closeButton = screen.getByTitle("Close dialog");
+await userEvent.click(closeButton);
+```
+
+### ByTestId
+
+`getByTestId` используется как последний вариант, когда другие методы не подходят. Например, если вы используете `screen.getByTestId("submit-button")`, то найдте элемент с атрибутом `data-testid="submit-button"`
+
+```javascript
+import { screen } from "@testing-library/dom";
+import userEvent from "@testing-library/user-event";
+
+// Базовое использование
+const submitButton = screen.getByTestId("submit-button");
+await userEvent.click(submitButton);
+```
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx
index de250999..035e2ea5 100644
--- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx
@@ -4,36 +4,59 @@ sidebar_position: 1
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
+import Admonition from "@theme/Admonition";
-# Установка {#install}
+# Установка и настройка
-Запустите установщик testplane с помощью `npm`.
+## Системные требования
+
+Чтобы начать работу с testplane, установите `Node.js` версии 18.0 и выше.
+
+## Установка {#install}
+
+Для запуска установщика testplane, с помощью `npm` выполните следующую команду:
```bash
npm init testplane@latest YOUR_PROJECT_PATH
```
-Если вы не хотите использовать дефолты при инициализации проекта, а настроить его с помощью визарда, укажите опцию `-v`.
+Чтобы настроить проект, а не использовать дефолты при его инициализации, укажите опцию `-v`.
+
+После выполнения команды установки, в директории проекта появится следующий набор файлов и папок:
+
+```bash
+node_modules
+testplane-tests
+ example.testplane.ts
+ ts.config.json
+package-lock.json
+package.json
+testplane.config.ts
+```
## Настройка {#setup}
-После выполнения команды, указанной выше, в корне проекта сгенерится файл `testplane.config.ts` с базовой настройкой.
+В файле `testplane.config.ts` содержится базовый набор настроек для запуска тестов:
```typescript
export default {
- // https://testplane.io/ru/docs/v8/basic-guides/managing-browsers/
gridUrl: "local",
baseUrl: "http://localhost",
pageLoadTimeout: 0,
httpTimeout: 60000,
testTimeout: 90000,
resetCursor: false,
+
+ // В параметре sets содержится информация о директории, в которой находятся тесты
+ // и перечень браузеров, в которых они будут запускаться:
sets: {
desktop: {
files: ["testplane-tests/**/*.testplane.(t|j)s"],
browsers: ["chrome", "firefox"],
},
},
+
+ // В поле `browsers` описана конфигурация используемых браузеров:
browsers: {
chrome: {
headless: true,
@@ -48,9 +71,9 @@ export default {
},
},
},
+
plugins: {
"html-reporter/testplane": {
- // https://github.com/gemini-testing/html-reporter
enabled: true,
path: "testplane-report",
defaultView: "all",
@@ -60,39 +83,10 @@ export default {
};
```
-Вы можете загрузить браузеры, описанные в конфиге, отдельно от запуска самого Testplane:
+Чтобы загрузить браузеры, описанные в конфиге, отдельно от запуска самого Testplane, выполните команду:
```bash
npx testplane install-deps
```
Без предварительного запуска команды, недостающие браузеры будут автоматически загружены с первым запуском Testplane.
-
-## Создание теста {#test_creation}
-
-Перейдите в файл `tests/example.testplane.js` с тестом. В нем вы можете посмотреть пример теста или написать свой. Например,
-
-```javascript
-describe("github", async function () {
- it("should find testplane", async function ({ browser }) {
- await browser.url("https://github.com/gemini-testing/testplane");
- const elem = await browser.$("#readme h1");
-
- await expect(elem).toHaveText("Testplane");
- });
-});
-```
-
-## Запуск теста {#test_running}
-
-Теперь вы можете запустить тесты:
-
-```bash
-npx testplane
-```
-
-или запустить gui-режим и запустить тест через интерфейс в браузере
-
-```bash
-npx testplane gui
-```
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx
index 2461ca29..c0b74b3f 100644
--- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx
@@ -2,54 +2,174 @@
sidebar_position: 3
---
-# Запуск тестов
+# Запуск и отладка
-Используйте команду `npx testplane` для запуска всех тестов в вашем проекте.
+## Запуск тестов
-## Запуск конкретного файла
+Для запуска тестов используйте команду:
-Если вы хотите запустить всю группу тестов, которые находятся в конкретном файле, то укажите путь к этому файлу в качестве входного параметра для testplane:
+```bash
+npx testplane
+```
+
+Также тесты можно запускать в `gui`-режиме, для этого выполните команду:
```bash
-testplane src/features/Reviews/Reviews.test/MyReview/MyReview.a11y@touch-phone.testplane.js
+npx testplane gui
```
-## Опция `--grep`
+### Запуск конкретного теста
+
+У вас имеется набор тестов и вам нужно запустить только один из них.
+
+```javascript
+const assert = require("assert");
+
+describe("tests", () => {
+ it("Проверка отображения главной страницы", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const title = await browser.getTitle();
+ assert.ok(title.includes("Testplane"));
+ });
+
+ it("Проверка наличия логотипа на главной странице", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const logo = await browser.$("a.navbar__brand");
+ const isDisplayed = await logo.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+
+ it("Проверка навигационного меню", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const menuItems = await browser.$$("nav.navbar a.navbar__item");
+ assert.ok(menuItems.length > 0);
+ });
+
+ it("Проверка наличия поля поиска", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const searchButton = await browser.$("button.DocSearch");
+ const isExisting = await searchButton.isExisting();
+ assert.strictEqual(isExisting, true);
+ });
+});
+```
-Если же вы хотите запустить конкретный тест, то воспользуйтесь опцией `--grep`, указав в качестве ее значения полное имя теста:
+В таком случае выполните команду:
```bash
-testplane --grep "Доступность Оставление отзыва"
+testplane --grep "Проверка наличия поля поиска"
```
-## Директива `.only`
+В кавычках вам необходимо передать содержимое скобок ключевого слова `it`.
-Ещё вы можете воспользоваться директивой `.only` для набора тестов `describe` и конкретного теста `it`, аналогично тому как это реализовано в `mocha` (см. раздел [exlusive tests](https://mochajs.org/#exclusive-tests)):
+### Запуск тестов в конкретных браузерах
-Например:
+По умолчанию тесты запускаются в тех браузерах, которые указаны в файле `testplane.config.ts`.
```javascript
-describe.only("Доступность", function () {
- // набор тестов...
-});
+browsers: ["chrome", "firefox"];
+```
+
+При выполнении команды `npx testplane` тесты запустятся в браузерах Google Chrome и Mozila Firefox.
+
+```bash
+# Запуск во всех браузерах (по умолчанию)
+testplane
+```
+
+Чтобы выполнить тесты в конкретном браузере, используйте команду:
+
+```bash
+# Запуск только в Chrome
+testplane --browser chrome
```
-или
+Также вы можете указать конкретный браузер для работы в теле теста.
```javascript
-it.only("Оставление отзыва", async function () {
- // код теста...
+// tests/browser-specific.test.js
+describe("Browser specific tests", () => {
+ it("should work in all browsers", async ({ browser }) => {
+ await browser.url("https://example.com");
+ });
+
+ // Пропустить тест в Safari
+ testplane.skip.in("safari", "Feature not supported in Safari");
+ it("should work only in Chrome and Firefox", async ({ browser }) => {
+ await browser.url("https://example.com");
+ // ... тело теста
+ });
+
+ // Запустить только в Chrome
+ testplane.only.in("chrome");
+ it("should work only in Chrome", async ({ browser }) => {
+ await browser.url("https://example.com");
+ // ... тело теста
+ });
});
```
-## Запуск тестов несколько раз {#running_tests_multiple_times}
-Иногда может быть полезным запустить один и тот же тест несколько раз — например, для проверки стабильности. Плагин [@testplane/test-repeater][testplane-test-repeater] позволяет запустить тесты заданное количество раз.
+### Запуск теста из конкретного файла
-После установки и включения плагина вы можете запустить тесты нужное количество раз, используя следующую команду:
+Чтобы запустить тесты из конкретного файла, выполните команду:
```bash
-npx testplane --test-repeater-repeat 5 --grep 'Имя теста'
+# Запуск конкретного файла
+testplane ../testplane-tests/example.testplane.ts
+```
+
+Где `../testplane-tests/example.testplane.ts` это путь к файлу с тестами.
+
+### Режим пользовательского интерфейса
+
+В Testplane вы можете работать с тестами в UI формате с помощью Testplane UI.
+
+
+
+О процессах установки и настройки Testplane UI вы можете прочитать в разделе [UI.](..//html-reporter//overview.mdx)
+
+## Отладка
+
+### Отладка в gui-формате
+
+Отслеживать процесс выполнения тестов очень легко, если запустить их в `gui`-режиме. В подобном формате работы html-reporter продемонстрирует, какие тесты были успешно выполнены, а в каких присутствуют ошибки и какого они характера.
+
+
+
+### Browser.debug()
+
+В Testplane имеется встроенный инструмент для отладки — `browser.debug`.
+
+```javascript
+it("отладка с паузой", async ({ browser }) => {
+ // Открываем тестируемую страницу
+ await browser.url("/page");
+
+ // browser.debug() останавливает выполнение теста
+ // и открывает интерактивную консоль (REPL - Read-Eval-Print Loop)
+ await browser.debug();
+
+ // После вызова debug() тест приостанавливается
+ // В консоли можно вводить команды WebdriverIO в реальном времени:
+
+ // Примеры команд, которые можно вводить в REPL:
+ // > await browser.$('.button').click() - кликнуть по кнопке
+ // > await browser.getTitle() - получить заголовок страницы
+ // > await browser.$$('.items') - найти все элементы
+ // > .exit - выйти из режима отладки
+
+ // Этот код выполнится только после выхода из debug()
+ await browser.$(".button").click();
+});
```
-[testplane-test-repeater]: ../../plugins/testplane-test-repeater
+### Отладка через Testplane UI
+
+Наиболее удобным способом для работы с отладкой тестов является UI режим, в нем вы можете в реальном времени наблюдать выполнения тестов.
+
+
+
+И находить нестабильные тесты, медленные тесты или другие проблемы с помощью опций «сортировка» и «группировка».
+
+
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx
index 9b4bed96..b4f5dd7b 100644
--- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx
@@ -5,4 +5,560 @@ draft: true
# Написание тестов
-
+## Структура теста
+
+Блок `describe` предназначен для группировки связанных тестов.
+
+```javascript
+describe("Название группы тестов", () => {
+ it("описание того, что должно произойти", async ({ browser }) => {
+ // Тело теста
+ });
+});
+```
+
+В блоке `it` описываются тестовые сценарии.
+
+```javascript
+it("описание того, что должно произойти", async ({ browser }) => {
+ // Тело теста
+});
+```
+
+После установки testplane, вы можете ознакомиться с примером теста, для этого перейдите в папку `testplane-tests` и откройте файл `example.testplane.ts`.
+
+```javascript
+const assert = require("assert");
+
+describe("test examples", () => {
+ it("docs search test", async ({ browser }) => {
+ await browser.openAndWait("https://testplane.io/");
+
+ // Find by tag name
+ const navBar = await browser.$("nav");
+
+ // Find by aria-label
+ await navBar.$("aria/Search").click();
+
+ // Find by placeholder
+ const fileSearchInput = await browser.findByPlaceholderText("Search docs");
+ await fileSearchInput.waitForDisplayed();
+ await fileSearchInput.setValue("config");
+
+ // Find by id
+ const fileSearchResults = await browser.$("#docsearch-list");
+
+ // Find by role
+ const fileSearchResultsItems = await fileSearchResults.findAllByRole("option");
+
+ await expect(fileSearchResultsItems.length).toBeGreaterThan(1);
+ });
+});
+```
+
+## Базовый синтаксис
+
+### Навигация
+
+Для перемещения по страницам используйте метод:
+
+```javascript
+await browser.url("https://testplane.io/ru/");
+```
+
+Если на странице имеются элементы, которые отображаются с задержкой, для корректного выполнения тестов укажите явное ожидание:
+
+```javascript
+await browser.url("https://testplane.io/ru/");
+await browser.$("h1").waitForExist({ timeout: 5000 });
+const title = await browser.$("h1").getText();
+```
+
+Либо используйте команду:
+
+```javascript
+await browser.openAndWait("https://testplane.io/ru/");
+```
+
+Команда `await browser.openAndWait()` по умолчанию дожидается загрузки всех необходимых элементов на странице.
+
+### Селекторы
+
+Testplane поддерживает различные стратегии поиска элементов: `CSS` селекторы (самые распространенные), текстовые селекторы (по содержимому), `XPath` для сложных запросов. Метод `$()` возвращает первый найденный элемент, а `$$()` — массив всех подходящих элементов:
+
+```javascript
+const assert = require("assert");
+
+describe("tests", () => {
+ it("Проверка отображения главной страницы", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const title = await browser.getTitle();
+ assert.ok(title.includes("Testplane"));
+ });
+
+ it("Проверка наличия логотипа на главной странице", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const logo = await browser.$("a.navbar__brand");
+ const isDisplayed = await logo.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+
+ it("Проверка навигационного меню", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const menuItems = await browser.$$("nav.navbar a.navbar__item");
+ assert.ok(menuItems.length > 0);
+ });
+
+ it("Проверка наличия поля поиска", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+ const searchButton = await browser.$("button.DocSearch");
+ const isExisting = await searchButton.isExisting();
+ assert.strictEqual(isExisting, true);
+ });
+});
+```
+
+### Взаимодействия с элементами
+
+После знакомства с селекторами и нахождения элемента можно выполнить различные действия: клик, ввод текста, двойной клик.
+
+```javascript
+const assert = require("assert");
+
+describe("tests, () => {
+
+ it("Пример клика - открытие поиска", async ({browser}) => {
+ await browser.url("https://testplane.io/ru/");
+
+ // Клик по кнопке поиска
+ const searchButton = await browser.$("button.DocSearch");
+ await searchButton.waitForClickable({timeout: 5000});
+ await searchButton.click();
+ await browser.pause(1000);
+
+ // Проверяем, что модальное окно поиска появилось
+ const searchModal = await browser.$(".DocSearch-Modal");
+ const isDisplayed = await searchModal.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+
+ it("Пример ввода текста - поиск по документации", async ({browser}) => {
+ await browser.url("https://testplane.io/ru/");
+
+ // Открываем поиск
+ const searchButton = await browser.$("button.DocSearch");
+ await searchButton.waitForClickable({timeout: 5000});
+ await searchButton.click();
+ await browser.pause(500);
+
+ // Вводим текст в поле поиска
+ const searchInput = await browser.$("input.DocSearch-Input");
+ await searchInput.waitForDisplayed({timeout: 5000});
+ await searchInput.setValue("browser");
+ await browser.pause(1000);
+
+ // Проверяем, что текст введен
+ const inputValue = await searchInput.getValue();
+ assert.strictEqual(inputValue, "browser");
+ });
+
+ it("Пример двойного клика - выделение текста заголовка", async ({browser}) => {
+ await browser.url("https://testplane.io/ru/");
+
+ // Находим заголовок на главной странице
+ const heading = await browser.$("h1");
+ await heading.waitForDisplayed({timeout: 5000});
+ await heading.scrollIntoView();
+ await browser.pause(500);
+
+ // Двойной клик по заголовку
+ await heading.doubleClick();
+ await browser.pause(500);
+
+ // Проверяем, что элемент существует и отображается
+ const isDisplayed = await heading.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+});
+```
+
+### Assertions
+
+Testplane задействует `expect API` из `WebdriverIO` для проверки состояния элементов и страниц — это позволяет формулировать утверждения (`assertions`) о том, какими должны быть свойства элементов или страницы в целом.
+
+```javascript
+const assert = require("assert");
+
+describe("tests", () => {
+ it("WebdriverIO assert - проверка URL", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ // WebdriverIO expect для browser
+ await expect(browser).toHaveUrl("https://testplane.io/ru/");
+ });
+
+ it("WebdriverIO assert - проверка существования элемента", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const logo = await browser.$("a.navbar__brand");
+
+ // WebdriverIO expect для элемента
+ await expect(logo).toExist();
+ });
+
+ it("WebdriverIO assert - проверка видимости элемента", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const searchButton = await browser.$("button.DocSearch");
+
+ // WebdriverIO expect
+ await expect(searchButton).toBeDisplayed();
+ });
+
+ // Примеры с Jest ассертами
+ it("Jest assert - проверка заголовка страницы", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const title = await browser.getTitle();
+
+ // Jest expect
+ expect(title).toContain("Testplane");
+ });
+
+ it("Jest assert - проверка количества элементов", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const menuItems = await browser.$$("nav.navbar a.navbar__item");
+
+ // Jest expect
+ expect(menuItems.length).toBeGreaterThan(0);
+ });
+
+ it("Jest assert - проверка атрибута элемента", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const docsLink = await browser.$("a[href='/ru/docs/v8/']");
+ const href = await docsLink.getAttribute("href");
+
+ // Jest expect
+ expect(href).toBe("/ru/docs/v8/");
+ });
+
+ it("Jest assert - проверка URL с регулярным выражением", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const currentUrl = await browser.getUrl();
+
+ // Jest expect с regex
+ expect(currentUrl).toMatch(/testplane\.io/);
+ });
+});
+```
+
+### Хуки
+
+Хуки — это специальные функции, которые автоматически выполняются в определенные моменты жизненного цикла тестов. Они позволяют подготовить окружение перед тестами и очистить его после выполнения. По умолчанию доступны два вида хуков — `beforeEach` и `afterEach`, первый выполняется перед каждым тестом, а второй после.
+
+```javascript
+const assert = require("assert");
+
+describe("Примеры работы с хуками", () => {
+ // beforeEach - выполняется перед каждым тестом
+ beforeEach(async ({ browser }) => {
+ console.log("--- Выполняется BEFOREEACH - перед каждым тестом ---");
+ await browser.url("https://testplane.io/ru/");
+ await browser.pause(500);
+ });
+
+ // afterEach - выполняется после каждого теста
+ afterEach(async ({ browser }) => {
+ console.log("--- Выполняется AFTEREACH - после каждого теста ---");
+ const currentUrl = await browser.getUrl();
+ console.log("Текущий URL:", currentUrl);
+ // Можно делать скриншоты, очищать данные и т.д.
+ });
+
+ it("Тест 1 - проверка заголовка", async ({ browser }) => {
+ const title = await browser.getTitle();
+ assert.ok(title.includes("Testplane"));
+ });
+
+ it("Тест 2 - проверка логотипа", async ({ browser }) => {
+ const logo = await browser.$("a.navbar__brand");
+ const isDisplayed = await logo.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+
+ it("Тест 3 - проверка поиска", async ({ browser }) => {
+ const searchButton = await browser.$("button.DocSearch");
+ const isExisting = await searchButton.isExisting();
+ assert.strictEqual(isExisting, true);
+ });
+});
+
+describe("Пример вложенных describe с хуками", () => {
+ beforeEach(async ({ browser }) => {
+ console.log("--- OUTER BEFOREEACH ---");
+ await browser.url("https://testplane.io/ru/");
+ });
+
+ afterEach(async ({ browser }) => {
+ console.log("--- OUTER AFTEREACH ---");
+ });
+
+ it("Внешний тест", async ({ browser }) => {
+ const title = await browser.getTitle();
+ assert.ok(title.length > 0);
+ });
+
+ describe("Внутренний блок тестов", () => {
+ beforeEach(async ({ browser }) => {
+ console.log("--- INNER BEFOREEACH ---");
+ // Сначала выполнится outer beforeEach, потом этот
+ await browser.url("https://testplane.io/ru/docs/v8/");
+ });
+
+ afterEach(async ({ browser }) => {
+ console.log("--- INNER AFTEREACH ---");
+ // Сначала выполнится этот afterEach, потом outer
+ });
+
+ it("Внутренний тест 1", async ({ browser }) => {
+ const currentUrl = await browser.getUrl();
+ assert.ok(currentUrl.includes("docs"));
+ });
+
+ it("Внутренний тест 2", async ({ browser }) => {
+ const heading = await browser.$("h1");
+ const isDisplayed = await heading.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+ });
+});
+```
+
+### Ожидания
+
+Явные ожидания необходимы для работы с динамическим контентом, который загружается или изменяется асинхронно. Testplane автоматически ждет появления элементов, но для сложных сценариев можно использовать специальные методы ожидания.
+
+```javascript
+const assert = require("assert");
+
+describe("Примеры ожиданий в Testplane", () => {
+ it("Ожидание появления и кликабельности элемента", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ // Ожидаем, что кнопка поиска появится на странице
+ const searchButton = await browser.$("button.DocSearch");
+ await searchButton.waitForDisplayed({
+ timeout: 5000,
+ timeoutMsg: "Кнопка поиска не появилась в течение 5 секунд",
+ });
+
+ // Ожидаем, что элемент станет кликабельным
+ await searchButton.waitForClickable({
+ timeout: 3000,
+ timeoutMsg: "Кнопка поиска не стала кликабельной",
+ });
+
+ await searchButton.click();
+
+ // Ожидаем появления модального окна поиска
+ const searchModal = await browser.$(".DocSearch-Modal");
+ await searchModal.waitForDisplayed({ timeout: 3000 });
+
+ const isDisplayed = await searchModal.isDisplayed();
+ assert.strictEqual(isDisplayed, true);
+ });
+
+ it("Ожидание изменения текста элемента", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const heading = await browser.$("h1");
+
+ // Ожидаем, что элемент будет существовать
+ await heading.waitForExist({
+ timeout: 5000,
+ timeoutMsg: "Заголовок не найден на странице",
+ });
+
+ // Ожидаем, что у элемента будет определенный текст
+ await heading.waitUntil(
+ async function () {
+ const text = await this.getText();
+ return text.length > 0;
+ },
+ {
+ timeout: 5000,
+ timeoutMsg: "Текст заголовка не появился",
+ },
+ );
+
+ const text = await heading.getText();
+ assert.ok(text.length > 0);
+ });
+
+ it("Ожидание с использованием browser.waitUntil для проверки URL", async ({ browser }) => {
+ await browser.url("https://testplane.io/ru/");
+
+ const docsLink = await browser.$("a[href='/ru/docs/v8/']");
+ await docsLink.waitForExist({ timeout: 5000 });
+
+ // Используем JavaScript click для надежности
+ await browser.execute(el => el.click(), docsLink);
+
+ // Ожидаем изменения URL с помощью browser.waitUntil
+ await browser.waitUntil(
+ async () => {
+ const currentUrl = await browser.getUrl();
+ return currentUrl.includes("docs");
+ },
+ {
+ timeout: 5000,
+ timeoutMsg: "URL не изменился на страницу документации",
+ },
+ );
+
+ const finalUrl = await browser.getUrl();
+ assert.ok(finalUrl.includes("docs"));
+ });
+});
+```
+
+### Работа с формами
+
+Testplane предоставляет специальные методы для работы с различными элементами форм. Чекбоксы и радио-кнопки управляются через клик. Для выпадающих списков `(