From cfd392c54a4b54804024045c5d56526f90f554e3 Mon Sep 17 00:00:00 2001 From: Vasilii Mikhailovskii Date: Thu, 30 Oct 2025 23:13:13 +0200 Subject: [PATCH] docs: ru --- docs/_navbar.md | 3 + docs/index.html | 30 ++ docs/ru/_navbar.md | 3 + docs/ru/_sidebar_ru.md | 57 +++ docs/ru/api.md | 247 +++++++++ docs/ru/blog/index.md | 4 + docs/ru/blog/whats-new-in-v8.md | 209 ++++++++ docs/ru/cli.md | 66 +++ docs/ru/configuration/esm.md | 12 + docs/ru/configuration/index.md | 22 + docs/ru/configuration/multiple-projects.md | 122 +++++ docs/ru/configuration/options.md | 259 ++++++++++ docs/ru/faq.md | 32 ++ docs/ru/getting-started/add-fixtures.md | 36 ++ docs/ru/getting-started/index.md | 13 + docs/ru/getting-started/installation.md | 88 ++++ docs/ru/getting-started/write-first-test.md | 123 +++++ docs/ru/guides/component-tests.md | 107 ++++ docs/ru/guides/debugging.md | 25 + docs/ru/guides/env-variables.md | 15 + docs/ru/guides/env-vars.md | 62 +++ docs/ru/guides/fix-with-ai.md | 140 ++++++ docs/ru/guides/ide-integration.md | 44 ++ docs/ru/guides/ignore-generated-files.md | 15 + docs/ru/guides/index.md | 14 + docs/ru/guides/migration-v7.md | 253 ++++++++++ docs/ru/guides/ui-mode.md | 22 + docs/ru/guides/usage-with-browserstack.md | 54 ++ docs/ru/guides/usage-with-currents.md | 64 +++ docs/ru/guides/usage-with-nx.md | 84 ++++ docs/ru/guides/usage-with-saucelabs.md | 112 +++++ docs/ru/index.md | 106 ++++ docs/ru/pickles.md | 55 ++ docs/ru/reporters/allure.md | 39 ++ docs/ru/reporters/cucumber.md | 354 +++++++++++++ docs/ru/reporters/index.md | 8 + docs/ru/reporters/playwright.md | 32 ++ docs/ru/sponsors.md | 22 + docs/ru/writing-features/auto-formatting.md | 18 + docs/ru/writing-features/chatgpt.md | 134 +++++ .../customize-examples-title.md | 90 ++++ docs/ru/writing-features/i18n.md | 24 + docs/ru/writing-features/index.md | 25 + docs/ru/writing-features/special-tags.md | 113 +++++ docs/ru/writing-features/tags-from-path.md | 49 ++ docs/ru/writing-steps/bdd-fixtures.md | 131 +++++ docs/ru/writing-steps/cucumber-style.md | 119 +++++ docs/ru/writing-steps/data-tables.md | 33 ++ docs/ru/writing-steps/decorators.md | 154 ++++++ docs/ru/writing-steps/hooks.md | 469 ++++++++++++++++++ docs/ru/writing-steps/index.md | 39 ++ docs/ru/writing-steps/keywords-matching.md | 48 ++ .../passing-data-between-scenarios.md | 76 +++ .../passing-data-between-steps.md | 84 ++++ docs/ru/writing-steps/playwright-style.md | 103 ++++ docs/ru/writing-steps/reusing-step-fn.md | 36 ++ docs/ru/writing-steps/scoped.md | 149 ++++++ docs/ru/writing-steps/snippets.md | 42 ++ scripts/validate-docs.ts | 6 +- 59 files changed, 4894 insertions(+), 1 deletion(-) create mode 100644 docs/_navbar.md create mode 100644 docs/ru/_navbar.md create mode 100644 docs/ru/_sidebar_ru.md create mode 100644 docs/ru/api.md create mode 100644 docs/ru/blog/index.md create mode 100644 docs/ru/blog/whats-new-in-v8.md create mode 100644 docs/ru/cli.md create mode 100644 docs/ru/configuration/esm.md create mode 100644 docs/ru/configuration/index.md create mode 100644 docs/ru/configuration/multiple-projects.md create mode 100644 docs/ru/configuration/options.md create mode 100644 docs/ru/faq.md create mode 100644 docs/ru/getting-started/add-fixtures.md create mode 100644 docs/ru/getting-started/index.md create mode 100644 docs/ru/getting-started/installation.md create mode 100644 docs/ru/getting-started/write-first-test.md create mode 100644 docs/ru/guides/component-tests.md create mode 100644 docs/ru/guides/debugging.md create mode 100644 docs/ru/guides/env-variables.md create mode 100644 docs/ru/guides/env-vars.md create mode 100644 docs/ru/guides/fix-with-ai.md create mode 100644 docs/ru/guides/ide-integration.md create mode 100644 docs/ru/guides/ignore-generated-files.md create mode 100644 docs/ru/guides/index.md create mode 100644 docs/ru/guides/migration-v7.md create mode 100644 docs/ru/guides/ui-mode.md create mode 100644 docs/ru/guides/usage-with-browserstack.md create mode 100644 docs/ru/guides/usage-with-currents.md create mode 100644 docs/ru/guides/usage-with-nx.md create mode 100644 docs/ru/guides/usage-with-saucelabs.md create mode 100644 docs/ru/index.md create mode 100644 docs/ru/pickles.md create mode 100644 docs/ru/reporters/allure.md create mode 100644 docs/ru/reporters/cucumber.md create mode 100644 docs/ru/reporters/index.md create mode 100644 docs/ru/reporters/playwright.md create mode 100644 docs/ru/sponsors.md create mode 100644 docs/ru/writing-features/auto-formatting.md create mode 100644 docs/ru/writing-features/chatgpt.md create mode 100644 docs/ru/writing-features/customize-examples-title.md create mode 100644 docs/ru/writing-features/i18n.md create mode 100644 docs/ru/writing-features/index.md create mode 100644 docs/ru/writing-features/special-tags.md create mode 100644 docs/ru/writing-features/tags-from-path.md create mode 100644 docs/ru/writing-steps/bdd-fixtures.md create mode 100644 docs/ru/writing-steps/cucumber-style.md create mode 100644 docs/ru/writing-steps/data-tables.md create mode 100644 docs/ru/writing-steps/decorators.md create mode 100644 docs/ru/writing-steps/hooks.md create mode 100644 docs/ru/writing-steps/index.md create mode 100644 docs/ru/writing-steps/keywords-matching.md create mode 100644 docs/ru/writing-steps/passing-data-between-scenarios.md create mode 100644 docs/ru/writing-steps/passing-data-between-steps.md create mode 100644 docs/ru/writing-steps/playwright-style.md create mode 100644 docs/ru/writing-steps/reusing-step-fn.md create mode 100644 docs/ru/writing-steps/scoped.md create mode 100644 docs/ru/writing-steps/snippets.md diff --git a/docs/_navbar.md b/docs/_navbar.md new file mode 100644 index 00000000..5e27d2ef --- /dev/null +++ b/docs/_navbar.md @@ -0,0 +1,3 @@ +- Translations + - [English](/index.md) + - [Русский](/ru/index.md) diff --git a/docs/index.html b/docs/index.html index 0a841b7e..bed76689 100644 --- a/docs/index.html +++ b/docs/index.html @@ -22,7 +22,24 @@ homepage: 'index.md', auto2top: true, loadSidebar: true, + loadNavbar: true, subMaxLevel: 3, + fallbackLanguages: ['en'], + nameLink: { + '/ru/': '/', + '/': '/', + }, + search: { + placeholder: { + '/ru/': 'Поиск', + '/': 'Search', + }, + noData: { + '/ru/': 'Нет результатов', + '/': 'No Results', + }, + pathNamespaces: ['/ru'], + }, topBanner: { position: 'relative', zIndex: '-1', @@ -42,7 +59,9 @@ '.*?/changelog': 'https://raw.githubusercontent.com/vitalets/playwright-bdd/docs/CHANGELOG.md', '.*?/license': 'https://raw.githubusercontent.com/vitalets/playwright-bdd/docs/LICENSE', + '^/ru(/.*|)/_sidebar.md': '/ru/_sidebar_ru.md', '/.*/_sidebar.md': '/_sidebar.md', + '/.*/_navbar.md': '/_navbar.md', }, }; @@ -68,5 +87,16 @@ gtag('js', new Date()); gtag('config', 'G-KFTCRSQYLJ'); + diff --git a/docs/ru/_navbar.md b/docs/ru/_navbar.md new file mode 100644 index 00000000..d7af90af --- /dev/null +++ b/docs/ru/_navbar.md @@ -0,0 +1,3 @@ +- Переводы + - [English](index.md) + - [Русский](ru/index.md) diff --git a/docs/ru/_sidebar_ru.md b/docs/ru/_sidebar_ru.md new file mode 100644 index 00000000..234e793f --- /dev/null +++ b/docs/ru/_sidebar_ru.md @@ -0,0 +1,57 @@ +* [**Начало работы**](ru/getting-started/index.md) + - [Установка](ru/getting-started/installation.md) + - [Первый BDD тест](ru/getting-started/write-first-test.md) + - [Добавление фикстур](ru/getting-started/add-fixtures.md) + +* [**Конфигурация**](ru/configuration/index.md) + - [Опции](ru/configuration/options.md) + - [Проекты](ru/configuration/multiple-projects.md) + - [ESM](ru/configuration/esm.md) + +* [**Написание фич**](ru/writing-features/index.md) + - [Специальные теги](ru/writing-features/special-tags.md) + - [Теги из пути](ru/writing-features/tags-from-path.md) + - [Локализация](ru/writing-features/i18n.md) + - [Авто-форматирование](ru/writing-features/auto-formatting.md) + - [Настройка заголовков примеров](ru/writing-features/customize-examples-title.md) + - [Использование ChatGPT](ru/writing-features/chatgpt.md) + +* [**Написание шагов**](ru/writing-steps/index.md) + - [Стиль Playwright](ru/writing-steps/playwright-style.md) + - [Стиль Cucumber](ru/writing-steps/cucumber-style.md) + - [Декораторы](ru/writing-steps/decorators.md) + - [Хуки](ru/writing-steps/hooks.md) + - [BDD фикстуры](ru/writing-steps/bdd-fixtures.md) + - [Передача данных между шагами](ru/writing-steps/passing-data-between-steps.md) + - [Передача данных между сценариями](ru/writing-steps/passing-data-between-scenarios.md) + - [Scoped определения шагов](ru/writing-steps/scoped.md) + - [Сопоставление ключевых слов](ru/writing-steps/keywords-matching.md) + - [Переиспользование функций шагов](ru/writing-steps/reusing-step-fn.md) + - [Таблицы данных](ru/writing-steps/data-tables.md) + - [Сниппеты](ru/writing-steps/snippets.md) + +* [**Репортеры**](ru/reporters/index.md) + - [Playwright](ru/reporters/playwright.md) + - [Cucumber](ru/reporters/cucumber.md) + - [Allure](ru/reporters/allure.md) + +* [**Руководства**](ru/guides/index.md) + - [🤖 Исправление с AI](ru/guides/fix-with-ai.md) + - [Миграция на v7](ru/guides/migration-v7.md) + - [Игнорирование сгенерированных файлов](ru/guides/ignore-generated-files.md) + - [Отладка](ru/guides/debugging.md) + - [UI режим](ru/guides/ui-mode.md) + - [Переменные окружения](ru/guides/env-vars.md) + - [Компонентные тесты](ru/guides/component-tests.md) + - [Интеграция с IDE](ru/guides/ide-integration.md) + - [Использование с Nx](ru/guides/usage-with-nx.md) + - [Использование с Currents](ru/guides/usage-with-currents.md) + - [Использование с SauceLabs](ru/guides/usage-with-saucelabs.md) + - [Использование с BrowserStack](ru/guides/usage-with-browserstack.md) + +* [**Блог**](ru/blog/index.md) +* [**API**](ru/api.md) +* [**CLI**](ru/cli.md) +* [**FAQ**](ru/faq.md) +* [**❤️ Спонсоры ❤️**](ru/sponsors.md) +* [**Список изменений**](changelog) diff --git a/docs/ru/api.md b/docs/ru/api.md new file mode 100644 index 00000000..5bbe4f6f --- /dev/null +++ b/docs/ru/api.md @@ -0,0 +1,247 @@ +# API + +### defineBddConfig + +Определяет BDD конфигурацию внутри конфигурационного файла Playwright. + +**Использование:** `defineBddConfig(config)` + +**Параметры:** + * `config` *object* - BDD [конфигурация](configuration/index.md) + +**Возвращает:** *string* - Директория, где будут сгенерированы тестовые файлы. + +### defineBddProject +
С версии v7.0.0
+ +Тонкая обертка вокруг `defineBddConfig()`, которая упрощает BDD конфигурацию для проектов Playwright. Она принимает имя проекта и автоматически устанавливает [`outputDir`](configuration/options.md#outputdir) на основе этого имени. Функция возвращает объект `{ name, testDir }`, который может быть объединен с конфигурацией проекта с помощью оператора распространения. + +**Использование:** `defineBddProject(config)` + +**Параметры:** + * `config` *object* - BDD [конфигурация](configuration/index.md) + имя проекта `{ name: string }` + +**Возвращает:** *{ name, testDir }* - Объект, содержащий имя проекта и директорию сгенерированных тестов. + +Пример: +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddProject } from 'playwright-bdd'; + +export default defineConfig({ + projects: [ + { + ...defineBddProject({ + name: 'foo', + features: '*.feature', + steps: 'steps/*.ts', + }), // -> { name: 'foo', testDir: '.features-gen/foo' } + }, + ] +}); +``` + +### cucumberReporter + +Вспомогательная функция для вывода результатов тестов в различных [репортерах Cucumber](reporters/cucumber.md). + +**Использование:** `cucumberReporter(reporter[, options])` + +**Параметры:** + * `reporter` *string* - Имя репортера Cucumber (`html|json|junit|message`) или путь к пользовательскому файлу репортера. + * `options` *object* - Опции репортера Cucumber. + +**Возвращает:** *array* - Кортеж конфигурации репортера Playwright. + +Пример использования в `playwright.config.ts`: +```ts +import { cucumberReporter } from 'playwright-bdd'; + +export default defineConfig({ + reporter: [ + cucumberReporter('html', { outputFile: `reports/report.html` }), + ], + // ...другие опции +}); +``` + +### createBdd + +Создает функции для определения шагов и хуков. + +**Использование:** `createBdd([test][, options])` + +> До Playwright-BDD **v7**, второй параметр был `WorldConstructor`. + +**Параметры:** + * `test` *object* - Экземпляр теста для предоставления доступа к пользовательским фикстурам в шагах. + * `options` *object* - Опции: + - `worldFixture` *string* - Имя фикстуры, которая будет использоваться как World в шагах в стиле cucumber. + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) по умолчанию, которое будет применено ко всем шагам/хукам. + +**Возвращает:** *object* - `{ Given, When, Then, Step, BeforeScenario, AfterScenario, BeforeWorker, AfterWorker, Before, After, BeforeAll, AfterAll }` + +По умолчанию созданные функции работают с шагами в [стиле Playwright](writing-steps/playwright-style.md). Если `options.worldFixture` определен, созданные функции работают с шагами в [стиле Cucumber](writing-steps/cucumber-style.md). + +### Given / When / Then / Step + +Функции для определений шагов. + +**Использование:** + - `Given(pattern[, options], fn)` + - `When(pattern[, options], fn)` + - `Then(pattern[, options], fn)` + - `Step(pattern[, options], fn)` + +**Параметры:** + * `pattern` *string | regexp* - Строка [выражения Cucumber](https://github.com/cucumber/cucumber-expressions) или RegExp. + * `options` *object* - Опции шага: + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для привязки этого шага к конкретным фичам/сценариям. + * `fn` *function* - Функция шага `(fixtures, ...args) => void`: + - `fixtures` *object* - Фикстуры Playwright (опущены в стиле cucumber). + - `...args` *array* - Аргументы, захваченные из паттерна шага. + +**Возвращает:** *function* - Функция для вызова этого шага из других шагов. + +### BeforeStep + +Определяет хук, который запускается **перед каждым шагом**. Вы можете нацелить хук на конкретный шаг, предоставив опцию `tags`. + +**Использование:** `BeforeStep([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для нацеливания этого хука на конкретные фичи/шаги. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Фикстуры Playwright: + - `$testInfo` *object* - Playwright [testInfo](https://playwright.dev/docs/api/class-testinfo). + - `$tags` *string[]* - Список тегов для текущего шага. + - Любые другие встроенные и пользовательские фикстуры. + +### AfterStep + +Определяет хук, который запускается **после каждого сценария**. Вы можете нацелить хук на конкретный шаг, предоставив опцию `tags`. + +**Использование:** `AfterStep([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для нацеливания этого хука на конкретные фичи/шаги. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Фикстуры Playwright: + - `$testInfo` *object* - Playwright [testInfo](https://playwright.dev/docs/api/class-testinfo). + - `$tags` *string[]* - Список тегов для текущего шага. + - Любые другие встроенные и пользовательские фикстуры. + +### BeforeScenario / Before + +Определяет хук, который запускается **перед каждым сценарием**. Вы можете нацелить хук на конкретные сценарии, предоставив опцию `tags`. `BeforeScenario` и `Before` - это псевдонимы. + +**Использование:** `BeforeScenario([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для нацеливания этого хука на конкретные фичи/сценарии. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Фикстуры Playwright: + - `$testInfo` *object* - Playwright [testInfo](https://playwright.dev/docs/api/class-testinfo). + - `$tags` *string[]* - Список тегов для текущего сценария. + - Любые другие встроенные и пользовательские фикстуры. + +### AfterScenario / After + +Определяет хук, который запускается **после каждого сценария**. Вы можете нацелить хук на конкретные сценарии, предоставив опцию `tags`. `AfterScenario` и `After` - это псевдонимы. + +**Использование:** `AfterScenario([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для нацеливания этого хука на конкретные фичи/сценарии. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Фикстуры Playwright: + - `$testInfo` *object* - Playwright [testInfo](https://playwright.dev/docs/api/class-testinfo). + - `$tags` *string[]* - Список тегов для текущего сценария. + - Любые другие встроенные и пользовательские фикстуры. + +### BeforeWorker / BeforeAll + +Определяет хук, который запускается **один раз в каждом воркере**, перед всеми сценариями. Вы можете нацелить хук на конкретные сценарии, предоставив опцию `tags`. `BeforeWorker` и `BeforeAll` - это псевдонимы. + +> Обратите внимание, что для хуков воркера имеет смысл предоставлять только *теги уровня фичи*. Теги уровня сценария все равно запустят хук для всего файла фичи, а не для конкретного сценария. + +**Использование:** `BeforeWorker([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для нацеливания этого хука на конкретные фичи. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Playwright [фикстуры с областью видимости воркера](https://playwright.dev/docs/test-fixtures#worker-scoped-fixtures): + - `$workerInfo` *object* - Playwright [workerInfo](https://playwright.dev/docs/api/class-workerinfo). + - Любые другие встроенные и пользовательские **фикстуры с областью видимости воркера**. + +?> Если вам нужно запустить хук **один раз для всех воркеров**, ознакомьтесь с [Запуск хука один раз](writing-steps/hooks.md#running-hook-once). + +### AfterWorker / AfterAll + +Определяет хук, который запускается **один раз в каждом воркере**, после всех сценариев. Вы можете нацелить хук на конкретные сценарии, предоставив опцию `tags`. `AfterWorker` и `AfterAll` - это псевдонимы. + +> Обратите внимание, что для хуков воркера имеет смысл предоставлять только *теги уровня фичи*. Теги уровня сценария все равно запустят хук для всего файла фичи, а не для конкретного сценария. + +**Использование:** `AfterWorker([options,] hookFn)` + +**Параметры:** + * `options` *string | object* + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для привязки этого хука к конкретным фичам. + - `name` *string* - Необязательное имя для этого хука для отчетности. + - `timeout` *number* - Таймаут для этого хука в миллисекундах. + * `hookFn` *Function* - Функция хука `(fixtures?) => void`: + - `fixtures` *object* - Playwright [фикстуры с областью видимости воркера](https://playwright.dev/docs/test-fixtures#worker-scoped-fixtures): + - `$workerInfo` *object* - Playwright [workerInfo](https://playwright.dev/docs/api/class-workerinfo). + - Любые другие встроенные и пользовательские **фикстуры с областью видимости воркера**. + +### @Fixture + +Декоратор класса для привязки Page Object Model (POM) к имени фикстуры. + +**Использование:** `@Fixture(nameOrOptions)` + +**Параметры:** + * `nameOrOptions` *string* - Имя фикстуры для данного класса. + * `nameOrOptions` *object* - Опции фикстуры: + - `name` *string* - Имя фикстуры для данного класса. + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для привязки всех шагов этого класса к конкретным фичам/сценариям. + +Также возможно предоставить тип `test` в качестве обобщенного параметра, чтобы ограничить `fixtureName` доступными именами фикстур: +```ts +import { Fixture } from 'playwright-bdd/decorators'; +import type { test } from './fixtures'; + +export +@Fixture('todoPage') +class TodoPage { ... }; +``` + +### @Given / @When / @Then / @Step + +Декоратор для пометки метода как BDD шага. + +**Использование:** + - `@Given(pattern[, options])` + - `@When(pattern[, options])` + - `@Then(pattern[, options])` + - `@Step(pattern[, options])` + +**Параметры:** + * `pattern` *string | regexp* - Паттерн шага как [выражение cucumber](https://github.com/cucumber/cucumber-expressions) или RegExp. + * `options` *object* - Опции шага: + - `tags` *string* - [Выражение тегов](https://github.com/cucumber/tag-expressions) для привязки этого шага к конкретным фичам/сценариям. diff --git a/docs/ru/blog/index.md b/docs/ru/blog/index.md new file mode 100644 index 00000000..8320edfb --- /dev/null +++ b/docs/ru/blog/index.md @@ -0,0 +1,4 @@ +# Блог Playwright-BDD + +- [Что нового в Playwright-BDD v8](ru/blog/whats-new-in-v8.md) + diff --git a/docs/ru/blog/whats-new-in-v8.md b/docs/ru/blog/whats-new-in-v8.md new file mode 100644 index 00000000..c8ccd8e5 --- /dev/null +++ b/docs/ru/blog/whats-new-in-v8.md @@ -0,0 +1,209 @@ +# Что нового в Playwright-BDD v8 + +
16-ДЕК-2024
+ +?> :fire: **Playwright-BDD v8** наполнен множеством обновлений для улучшения вашего опыта BDD тестирования. + + + +- [Улучшения тегирования](#tagging-enhancements) + - [Теги из пути](#tags-from-path) + - [Scoped определения шагов](#scoped-step-definitions) + - [Тегированные `BeforeAll` и `AfterAll`](#tagged-beforeall-and-afterall) + - [Теги по умолчанию](#default-tags) +- [Улучшенные опции конфигурации](#improved-configuration-options) + - [`featuresRoot` как директория по умолчанию](#featuresroot-as-a-default-directory) + - [Новая опция: `missingSteps`](#new-option-missingsteps) + - [Новая опция: `matchKeywords`](#new-option-matchkeywords) + - [Значение по умолчанию для `quotes` установлено в `single`](#default-value-for-quotes-set-to-single) +- [Другие изменения](#other-changes) + - [Новые псевдонимы хуков](#new-hook-aliases) + - [Локализованные заголовки шагов](#localized-step-titles) + - [Обновление версии Playwright](#playwright-version-update) +- [Начало работы с v8](#getting-started-with-v8) + +## Улучшения тегирования + +### Теги из пути + +Управление тестовыми фичами и определениями шагов стало проще. В v8 вы теперь можете автоматически назначать теги фичам и шагам, используя **имена директорий или файлов с префиксом @**. Например: + +``` +features +├── @game <- устанавливает тег @game для всех файлов внутри +│ ├── game.feature +│ └── steps.ts +└── @video-player <- устанавливает тег @video-player для всех файлов внутри + ├── video-player.feature + └── steps.ts +``` + +В этой настройке теги `@game` и `@video-player` автоматически применяются к соответствующим фичам и шагам. Это устраняет необходимость в повторяющемся ручном тегировании и помогает связывать фичи с шагами. + +Смотрите больше деталей в документации: [теги из пути](writing-features/tags-from-path.md). + +### Scoped определения шагов + +Теперь вы можете ограничить определения шагов конкретными фичами или сценариями с помощью тегов. Просто передайте выражение `tags` во втором аргументе: + +```ts +When('I click the PLAY button', { tags: '@game' }, async () => { + // ... +}); +``` + +Это гарантирует, что один и тот же шаг может сосуществовать в нескольких фичах, упрощая поддержку больших проектов: + +```ts +When('start playing', { tags: '@game' }, async () => { ... }); +When('start playing', { tags: '@video-player' }, async () => { ... }); +``` + +Полная документация: [scoped определения шагов](writing-steps/scoped.md). + +### Тегированные `BeforeAll` и `AfterAll` +Хуки `BeforeAll` и `AfterAll` теперь поддерживают опции `name` и `tags`: + +```ts +BeforeAll({ name: 'populate db', tags: '@game' }, async () => { + // настройка воркера для игры +}); + +AfterAll({ name: 'cleanup db', tags: '@game' }, async () => { + // завершение воркера для игры +}); +``` + +Тегированные хуки будут выполняться только если соответствующая фича выполняется. + +?> Имейте в виду, что эти хуки **запускаются в каждом воркере**, аналогично хукам воркера Playwright. + +Полная документация: [Хуки](writing-steps/hooks.md). + +### Теги по умолчанию + +Если множественные определения шагов и хуки должны иметь одинаковые теги, вы можете предоставить эти теги по умолчанию через опцию `createBdd()`: + +```ts +const { BeforeAll, Before, Given } = createBdd(test, { + tags: '@game' // <- тег по умолчанию +}); + +// все функции ниже помечены `@game` +BeforeAll(async () => { ... }); +Before(async () => { ... }); +Given('a step', async () => { ... }); +``` + +Полный список [опций createBdd()](api.md#createbdd). + +## Улучшенные опции конфигурации + +### `featuresRoot` как директория по умолчанию +Начиная с Playwright-BDD v8, `featuresRoot` рассматривается как директория по умолчанию для фичей и шагов, если они не определены явно. Это упрощает конфигурацию для типичного проекта: +```ts +// до +const testDir = defineBddConfig({ + features: './features/**/*.feature', + steps: './features/steps/**/*.js', + featuresRoot: './features', +}); + +// после +const testDir = defineBddConfig({ + featuresRoot: './features', +}); +``` + +Документация для [`featuresRoot`](configuration/options.md#featuresroot). + +### Новая опция: `missingSteps` + +Контролируйте поведение когда определения шагов отсутствуют с помощью новой опции `missingSteps`. Выберите между: + +- `fail-on-gen` (по умолчанию): падение генерации тестов. +- `fail-on-run`: разрешает генерацию, но падает при выполнении. +- `skip-scenario`: помечает сценарий как `fixme` и пропускает его. + +Пример: +```ts +const testDir = defineBddConfig({ + missingSteps: 'skip-scenario', + // ... +}); +``` + +Документация для [`missingSteps`](configuration/options.md#missingsteps). + +### Новая опция: `matchKeywords` + +Новая опция `matchKeywords` переключает соответствие ключевых слов для определений шагов. Если включено, `Given`, `When` и `Then` в определениях строго соответствуют их соответствующим ключевым словам в файлах фичей. + +- `matchKeywords: false` (по умолчанию): ключевое слово определения шага не учитывается для соответствия + ```ts + // соответствует "Given a step", "When a step", "Then a step" + Given('a step', () => { ... }); + ``` + +- `matchKeywords: true`: ключевое слово определения шага учитывается для соответствия + ```ts + // соответствует только "Given a step" + Given('a step', () => { ... }); + ``` + +Больше деталей в [Соответствие ключевых слов](writing-steps/keywords-matching.md). + +### Значение по умолчанию для `quotes` установлено в `single` +Генерируемые тестовые файлы теперь используют одинарные кавычки по умолчанию, уменьшая потребность в escape символах и делая файлы чище. Чтобы вернуться к предыдущему поведению, установите опцию `quotes` вручную: +```ts +const testDir = defineBddConfig({ + quotes: 'double', + // ... +}); +``` + +## Другие изменения + +### Новые псевдонимы хуков +Представляем новые псевдонимы для хуков: + +- `BeforeAll` → `BeforeWorker` +- `AfterAll` → `AfterWorker` +- `Before` → `BeforeScenario` +- `After` → `AfterScenario` + +Использование новых псевдонимов рекомендуется, потому что они лучше выражают, когда хук выполняется. + +### Локализованные заголовки шагов +HTML репортер Playwright теперь показывает локализованные заголовки шагов с ключевыми словами: + +![Localized HTML report](./../../blog/_media/i18n-html-report.png) + +### Обновление версии Playwright +Минимальная версия Playwright была обновлена до самой ранней не-устаревшей: **1.41**. +Пожалуйста, обновите вашу зависимость `@playwright/test` при необходимости. + +?> Вы можете проверить устаревшие версии Playwright командой: `npm show @playwright/test@1 deprecated` + +--- + +Ознакомьтесь с полным списком изменений в [Changelog](changelog). + +## Начало работы с v8 + +Чтобы обновиться до v8, выполните следующие шаги: + +1. Обновите ваш пакет: + + ```bash + npm install -D playwright-bdd@latest + ``` + +2. Настройте ваш конфигурационный файл для включения новых опций по мере необходимости. +3. Просмотрите [Changelog](changelog) для потенциальных критических изменений и адаптируйте ваш проект соответственно. +4. Запустите ваши тесты, чтобы убедиться, что все работает как ожидается. + +> В случае каких-либо багов или вопросов, не стесняйтесь открыть [issue](https://github.com/vitalets/playwright-bdd/issues) на GitHub. + +Счастливого тестирования ❤️ + diff --git a/docs/ru/cli.md b/docs/ru/cli.md new file mode 100644 index 00000000..38d63e61 --- /dev/null +++ b/docs/ru/cli.md @@ -0,0 +1,66 @@ +# CLI + +## `bddgen test` (или просто `bddgen`) +Генерирует файлы тестов Playwright из Gherkin документов (файлов `.feature`). +Эта команда обычно за которой следует `npx playwright test` для запуска сгенерированных тестов. +Также предполагается, что существует `playwright.config.(ts|js)` с одним или несколькими вызовами [`defineBddConfig()`](configuration/index.md). + +Примеры: + +* Генерировать и запустить тестовые файлы используя `playwright.config.ts` в расположении по умолчанию (рабочая директория): + ``` + npx bddgen && npx playwright test + ``` + +* Использовать опцию `--tags` для генерации тестов с [фильтрацией по тегам](https://cucumber.io/docs/cucumber/api/?lang=javascript#tag-expressions): + ``` + npx bddgen --tags "@foo and not @bar" && npx playwright test + ``` + +* Использовать опцию `-c` / `--config` для установки пользовательской конфигурации. Примечание: одинаковая конфигурация должна быть предоставлена обеим командам `bddgen` и `playwright test`: + ``` + npx bddgen -c path/to/playwright.config.ts && npx playwright test -c path/to/playwright.config.ts + ``` + +* Использовать `-h` для показа справки: + ``` + npx bddgen test -h + # или для показа глобальной справки + npx bddgen -h + ``` + +## `bddgen export` +Выводит список всех найденных определений шагов. +Полезно для [генерации BDD сценариев с ChatGPT](writing-features/chatgpt.md). +``` +$ npx bddgen export +``` +Пример вывода: +``` +Using config: playwright.config.ts +List of all steps (4): + +* Given I am on todo page +* When I add todo {string} +* When I remove todo {string} +* Then visible todos count is {int} +``` +#### Опции +* `--config` - путь к конфигурации Playwright +* `--unused-steps` - вывести только неиспользуемые шаги + +## `bddgen env` +Отображает информацию о текущем окружении: +``` +$ npx bddgen env +``` +Пример вывода: +``` +Playwright-BDD environment info: + +platform: darwin +node: v18.16.0 +playwright-bdd: v5.1.1 +@playwright/test: v1.36.2 +@cucumber/cucumber: v9.2.0 +``` diff --git a/docs/ru/configuration/esm.md b/docs/ru/configuration/esm.md new file mode 100644 index 00000000..ca8de7f9 --- /dev/null +++ b/docs/ru/configuration/esm.md @@ -0,0 +1,12 @@ +# ESM + +Ваш проект работает в [ESM](https://nodejs.org/api/esm.html), если: + * `package.json` содержит `"type": "module"` + * `tsconfig.json` содержит `"module": "ESNext"` + +С версии Playwright-BDD **v7** и Playwright **v1.41** вам не нужно использовать `--loader ts-node/esm` для ESM проектов. Просто запускайте как обычно: +``` +npx bddgen && npx playwright test +``` + +Вы можете ознакомиться с полностью рабочим ESM проектом в [примерах](https://github.com/vitalets/playwright-bdd/tree/main/examples/esm). diff --git a/docs/ru/configuration/index.md b/docs/ru/configuration/index.md new file mode 100644 index 00000000..7f53c3e4 --- /dev/null +++ b/docs/ru/configuration/index.md @@ -0,0 +1,22 @@ +# Конфигурация + +Конфигурация передается в `defineBddConfig()` внутри файла конфигурации Playwright. +Возвращаемое значение `defineBddConfig()` — это разрешенная выходная директория, где будут сгенерированы тестовые файлы. Удобно использовать её в качестве опции `testDir` для Playwright. + +Пример конфигурации в `playwright.config.ts`: +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'feature/*.feature', + steps: 'steps/**/*.ts', + // ...другие опции playwright-bdd +}); + +export default defineConfig({ + testDir, +}); +``` + +Все относительные пути разрешаются от расположения файла конфигурации. diff --git a/docs/ru/configuration/multiple-projects.md b/docs/ru/configuration/multiple-projects.md new file mode 100644 index 00000000..663fd776 --- /dev/null +++ b/docs/ru/configuration/multiple-projects.md @@ -0,0 +1,122 @@ +# Проекты +Вы можете использовать Playwright-BDD с несколькими [проектами Playwright](https://playwright.dev/docs/test-projects). + +## Общие файлы фич + +Если все проекты используют **один и тот же набор файлов фич**, вы можете определить единую опцию `testDir` на корневом уровне конфигурации: +```ts +import { defineConfig, devices } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'feature/*.feature', + steps: 'steps/**/*.ts', +}); + +export default defineConfig({ + testDir, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + ], +}); +``` + +## Разные файлы фич + +Если проекты используют **разные файлы фич**, вы должны определить отдельный `testDir` для каждого проекта: +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +export default defineConfig({ + projects: [ + { + name: 'project-one', + testDir: defineBddConfig({ + outputDir: '.features-gen/one', + features: 'project-one/*.feature', + steps: 'project-one/steps/*.ts', + }), + }, + { + name: 'project-two', + testDir: defineBddConfig({ + outputDir: '.features-gen/two', + features: 'project-two/*.feature', + steps: 'project-two/steps/*.ts', + }), + }, + ], +}); +``` + +?> Обратите внимание, что вы также должны установить уникальный `outputDir` для каждого проекта, чтобы избежать конфликтов. + +Для удобства существует вспомогательная функция [`defineBddProject()`](ru/api.md#definebddproject). В дополнение к стандартной BDD конфигурации, она принимает имя проекта и автоматически устанавливает `outputDir` на основе этого имени. Функция возвращает объект `{ name, testDir }`, который может быть объединен в конфигурацию проекта с помощью оператора расширения. + +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddProject } from 'playwright-bdd'; + +export default defineConfig({ + projects: [ + { + ...defineBddProject({ + name: 'project-one', + features: 'project-one/*.feature', + steps: 'project-one/steps/*.ts', + }), + }, + { + ...defineBddProject({ + name: 'project-two', + features: 'project-two/*.feature', + steps: 'project-two/steps/*.ts', + }), + }, + ], +}); +``` + +## Не-BDD проекты + +Вы можете иметь не-BDD проекты в той же конфигурации Playwright. Просто убедитесь, что не-BDD проекты имеют свой собственный `testDir`. См. пример в разделе **Аутентификация** ниже. + +## Аутентификация + +При использовании отдельного не-BDD проекта [для аутентификации](https://playwright.dev/docs/auth#basic-shared-account-in-all-tests), важно явно установить `testDir` для него: + +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'steps/*.ts', +}); + +export default defineConfig({ + testDir, + projects: [ + { + name: 'setup', + testDir: './setup-steps', // <-- установите testDir для проекта setup + testMatch: /setup\.ts/, + }, + { + name: 'chromium', + dependencies: ['setup'], + use: { + storageState: 'playwright/.auth/user.json', + }, + }, + ], +}); +``` diff --git a/docs/ru/configuration/options.md b/docs/ru/configuration/options.md new file mode 100644 index 00000000..babd66b0 --- /dev/null +++ b/docs/ru/configuration/options.md @@ -0,0 +1,259 @@ +# Опции + +## features + +?> С версии Playwright-BDD **v7** эта опция заменила опцию `paths` из Cucumber. + +- **Тип:** `string | string[]` +- **По умолчанию:** `undefined` + +Путь(и) к файлам фич. Может быть директорией или [glob-паттерном](https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#pattern-syntax). +Пример: `features/**/*.feature`. +Если вы не указываете расширение файла, по умолчанию используется `*.feature`. +Разрешается относительно расположения файла конфигурации. + +> С версии Playwright-BDD **v8** вы можете опустить опцию `features` и определить [`featuresRoot`](#featuresroot), которая служит общей базовой директорией как для фич, так и для шагов. Glob-паттерн для фич будет вычислен как `{featuresRoot} + /**/*.feature`. + +## steps + +?> С версии v7 эта опция заменила опции `require`, `import` и `requireModule` из Cucumber. + +- **Тип:** `string | string[]` +- **По умолчанию:** `undefined` + +Путь(и) к определениям шагов. Может быть директорией или [glob-паттерном](https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#pattern-syntax). +Пример: `steps/**/*.ts`. +Если вы не указываете расширение файла, по умолчанию используется `*.{js,mjs,cjs,ts,mts,cts}`. +Разрешается относительно расположения файла конфигурации. + +> С версии Playwright-BDD **v8** вы можете опустить опцию `steps` и определить [`featuresRoot`](#featuresroot), которая служит общей базовой директорией как для фич, так и для шагов. Glob-паттерн для шагов будет вычислен как `{featuresRoot} + /**/*.{js,mjs,cjs,ts,mts,cts}`. + +## outputDir + +- **Тип:** `string` +- **По умолчанию:** `.features-gen` + +Директория для вывода сгенерированных тестовых файлов. Разрешается относительно расположения файла конфигурации. + +## featuresRoot + +- **Тип:** `string` +- **По умолчанию:** *расположение файла конфигурации* + +Базовая директория для построения путей сгенерированных файлов внутри `outputDir`. Разрешается относительно расположения файла конфигурации. Обратите внимание, что `featuresRoot` это директория и не может содержать glob-паттерны (`*`). + +Поведение аналогично опции [rootDir](https://www.typescriptlang.org/tsconfig#rootDir) в TypeScript, которая устанавливает общего родителя для всех `.ts` файлов и определяет структуру `outDir`. + +
+ Пример + + Представьте следующую структуру проекта: + + ``` + features + feature1.feature + subdir + feature2.feature + playwright.config.ts + ``` + + Если вы генерируете тесты без `featuresRoot`, вы получите следующий вывод: + ``` + .features-gen + features + feature1.feature.spec.js + subdir + feature2.feature.spec.js + ``` + + Если вы не хотите включать директорию `features` в вывод, вы можете установить `featuresRoot: './features'` и тогда все выходные пути будут разрешены от неё: + ``` + .features-gen + feature1.feature.spec.js + subdir + feature2.feature.spec.js + ``` +
+ +С версии **Playwright-BDD v8** `featuresRoot` служит директорией по умолчанию как для `features`, так и для `steps`, если эти опции не определены явно. Это позволяет использовать более лаконичные конфигурации. + +До v8: +```js +const testDir = defineBddConfig({ + features: './features/**/*.feature', + steps: './features/steps/**/*.js', + featuresRoot: './features', +}); +``` + +С v8: +```js +const testDir = defineBddConfig({ + featuresRoot: './features', +}); +``` + +Вы все еще можете запустить подмножество фич при необходимости: +```js +const testDir = defineBddConfig({ + featuresRoot: './features', + features: './features/game/*.feature', // <- запустить только эти фичи +}); +``` + +## language + +- **Тип:** `string` +- **По умолчанию:** `en` + +[Язык](https://cucumber.io/docs/gherkin/reference/#spoken-languages) по умолчанию для ваших файлов фич. + +## aiFix + +- **Тип:** `object` +- **По умолчанию:** `undefined` + +Набор опций для исправления упавших тестов с помощью AI. + +#### Вложенные опции + * `promptAttachment` *boolean* - прикреплять ли AI промпт к упавшим тестам + * `promptAttachmentName` *string* - пользовательское имя для вложения промпта + * `promptTemplate` *string* - пользовательский шаблон для промпта (здесь [по умолчанию](https://github.com/vitalets/playwright-bdd/blob/main/src/ai/promptTemplate.ts)) + +Пример: + +```js +const testDir = defineBddConfig({ + aiFix: { + promptAttachment: true, + }, + // ...другие опции +}); +``` + +## examplesTitleFormat + +- **Тип:** `string` +- **По умолчанию:** `Example #<_index_>` + +Формат заголовка для примеров `Scenario Outline` в сгенерированных тестовых файлах. + +## quotes + +- **Тип:** `'single' | 'double' | 'backtick'` +- **По умолчанию:** `'single'` + +Стиль кавычек в сгенерированных тестовых файлах. + +## tags + +- **Тип:** `string` + +[Выражение с тегами](https://cucumber.io/docs/cucumber/api/?lang=javascript#tag-expressions) для фильтрации сценариев при генерации. Также может быть определено опцией CLI `--tags`. + +Пример: +```ts +const testDir = defineBddConfig({ + tags: '@desktop and not @slow', + // ... +}); +``` + +## missingSteps +
с версии v8
+ +- **Тип:** `'fail-on-gen' | 'fail-on-run' | 'skip-scenario'` +- **По умолчанию:** `'fail-on-gen'` + +Поведение при обнаружении отсутствующих шагов: +- `fail-on-gen` *(по умолчанию)* - генерация тестовых файлов завершится с ошибкой и отобразит [сниппеты](ru/writing-steps/snippets.md) кода для отсутствующих шагов +- `fail-on-run` - тестовые файлы будут сгенерированы, но запуск тестов завершится с ошибкой +- `skip-scenario` - тестовые файлы будут сгенерированы, но сценарии с отсутствующими шагами будут помечены как `fixme` + +## matchKeywords +
с версии v8
+ +- **Тип:** `boolean` +- **По умолчанию:** `false` + +Если включено, ключевое слово также учитывается при поиске определений шагов. См. [Сопоставление ключевых слов](ru/writing-steps/keywords-matching.md). + +## verbose + +- **Тип:** `boolean` +- **По умолчанию:** `false` + +Подробный вывод. + +## enrichReporterData + +!> С версии Playwright-BDD **v8** эта опция не используется и будет удалена в будущем. + +- **Тип:** `boolean` +- **По умолчанию:** `undefined` + +Если эта опция включена, Playwright-BDD добавит специальные вложения с BDD данными, необходимыми для отчетов Cucumber. Она включается автоматически, когда вы используете хелпер `cucumberReporter()`. Но для сценариев со [слиянием отчетов](reporters/cucumber.md#merge-reports) вам нужно вручную установить `enrichReporterData: true` при генерации **blob** отчета. + +## statefulPoms + +- **Тип:** `boolean` +- **По умолчанию:** `false` + +Установите эту опцию в `true`, если вы используете шаги-декораторы и ваши Page Object Models имеют состояние. Это включает более строгое угадывание фикстур в сценариях. + +**Пример** + +Представьте, что у вас следующая структура POM: +``` + BasePage + / \ +TodoPage TodoPage2 +``` +И следующий сценарий: +```gherkin +Scenario: scenario 1 + Given step from BasePage + When step from TodoPage + Then step from TodoPage2 +``` +Какой POM мы должны использовать для 1-го шага: `BasePage`, `TodoPage` или `TodoPage2`? + +* Если нет состояния в POM (`statefulPoms: false`): мы будем использовать `BasePage` +* Если есть состояние в POM (`statefulPoms: true`): этот сценарий выдаст ошибку, потому что для `TodoPage` / `TodoPage2` может быть важно вызвать предыдущие шаги + +## importTestFrom + +?> С версии **v7** вам, скорее всего, не нужна эта опция, она определяется автоматически из определений шагов. + +- **Тип:** `string` + +Путь к файлу, который экспортирует пользовательский `test` для использования в сгенерированных тестовых файлах. + +## paths + +!> Устарело, используйте [`features`](#features) вместо этого. + +- **Тип:** `string[]` +- **По умолчанию:** `features/**/*.{feature,feature.md}` + +Пути к файлам фич. [Подробнее в документации Cucumber](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#finding-your-features). + +## require + +!> Устарело, используйте [`steps`](#steps) вместо этого. + +- **Тип:** `string[]` +- **По умолчанию:** `features/**/*.(js)` + +Пути к определениям шагов в **CommonJS**. [Подробнее в документации Cucumber](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#finding-your-code). + +> Опция Cucumber `requireModule: ['ts-node/register']` не рекомендуется для Playwright-BDD. Компиляция TypeScript выполняется встроенным загрузчиком Playwright. + +## import + +!> Устарело, используйте [`steps`](#steps) вместо этого. + +- **Тип:** `string[]` +- **По умолчанию:** `features/**/*.(js)` + +Пути к определениям шагов в [ESM](ru/configuration/esm.md). diff --git a/docs/ru/faq.md b/docs/ru/faq.md new file mode 100644 index 00000000..aa05c362 --- /dev/null +++ b/docs/ru/faq.md @@ -0,0 +1,32 @@ +# FAQ + +### Зачем нужна генерация тестовых файлов? +Генерация тестовых файлов Playwright из BDD сценариев позволяет использовать все инструменты Playwright из коробки: + + * запускать отдельный тест с помощью [расширения VS Code](guides/ide-integration.md#vs-code) + * отлаживать и устанавливать точки останова на конкретных BDD шагах + * использовать режим `--ui` для отслеживания изменений + * делать все, что вы можете с обычными тестами Playwright + +Более того, это обеспечивает большую прозрачность того, как Playwright **видит** ваши BDD сценарии. + +Изначально Playwright-BDD пытался запускать BDD тесты на лету, внутри команды `npx playwright test`. Однако появилось несколько проблем: + +1. Слишком много перегенераций, потому что конфигурация Playwright выполняется много раз из разных источников: воркеров, расширения VS Code, UI режима и т.д. +2. Реализация watch режима сложна. +3. Отслеживание файлов в режиме `--ui` приводит к циклической зависимости: изменение в тестовых файлах запускает выполнение теста, который повторно импортирует конфигурацию и вызывает еще одно изменение в тестовых файлах. + +На данный момент разделение **генерации тестов** от **выполнения тестов** оказывается лучшим вариантом. + +### Могу ли я вручную применить `test.use()` в сгенерированном файле? +Нет. Генерация тестовых файлов полностью автоматизирована без ручных правок. Вместо использования `test.use`, который влияет на все тесты в файле, вы можете [использовать теги](writing-steps/bdd-fixtures.md#tags) и пользовательские фикстуры. Этот подход более гибкий и позволяет выборочно изменять настройки для конкретных сценариев или тестов. + +### Как сделать BDD ценным для моего проекта? +Главное - **BDD это техника совместной работы**. + +Пишите BDD примеры вместе с вашей командой во время звонков и обсуждений. Используйте это как фреймворк для уточнения требований между бизнесом, QA и разработчиками. Это должно помочь всем быть на одной волне вместо бесконечных встреч туда-сюда. + +Для более подробной информации, ознакомьтесь с [этим постом](https://news.ycombinator.com/item?id=10194242) от создателя Cucumber и [статьей Real-World BDD](https://www.serenity-dojo.com/minimal-bdd). + + + diff --git a/docs/ru/getting-started/add-fixtures.md b/docs/ru/getting-started/add-fixtures.md new file mode 100644 index 00000000..b80163cb --- /dev/null +++ b/docs/ru/getting-started/add-fixtures.md @@ -0,0 +1,36 @@ +# Добавление фикстур + +По мере роста ваших тестов вам, скорее всего, понадобятся [фикстуры](https://playwright.dev/docs/test-fixtures) Playwright. Это означает, что вы будете использовать пользовательский экземпляр `test`, созданный с помощью `test.extend()`. Для таких случаев вы должны передать пользовательский экземпляр test в функцию `createBdd()`, чтобы иметь доступ ко всем вашим фикстурам внутри определений шагов. + +### Рекомендуемая настройка + +Вызовите `createBdd(test)` в том же файле, где вы определяете пользовательский test, и экспортируйте `test` и `Given / When / Then`: + +```ts +// fixtures.ts +import { test as base, createBdd } from 'playwright-bdd'; + +type Fixtures = { + // ...установите типы ваших пользовательских фикстур +}; + +export const test = base.extend({ + // ...реализуйте ваши пользовательские фикстуры +}); + +export const { Given, When, Then } = createBdd(test); +``` + +> Убедитесь, что вы экспортируете переменную `test`, потому что она используется в сгенерированных тестовых файлах. + +Теперь вы можете писать определения шагов с пользовательскими фикстурами: + +```ts +// steps.ts + +import { Given, When, Then } from './fixtures'; + +Given('My step', async ({ myFixture }) => { + // ...код шага, который использует myFixture +}); +``` diff --git a/docs/ru/getting-started/index.md b/docs/ru/getting-started/index.md new file mode 100644 index 00000000..9cb4eb67 --- /dev/null +++ b/docs/ru/getting-started/index.md @@ -0,0 +1,13 @@ +# Начало работы + +Добро пожаловать в Playwright-BDD! + +Это руководство знакомит вас с основами BDD тестирования с помощью Playwright. Оно включает следующие шаги: + +1. Установка пакета `playwright-bdd` +2. Конфигурация +3. Написание фич с синтаксисом `Given-When-Then` +4. Реализация шагов на JavaScript +5. Запуск тестов и получение HTML отчета + +Продолжите с [установки](ru/getting-started/installation.md). diff --git a/docs/ru/getting-started/installation.md b/docs/ru/getting-started/installation.md new file mode 100644 index 00000000..b1cab39a --- /dev/null +++ b/docs/ru/getting-started/installation.md @@ -0,0 +1,88 @@ +# Установка + +Вы можете установить Playwright-BDD с помощью различных менеджеров пакетов: + +- [с Npm](#npm) +- [с Pnpm](#pnpm) +- [с Yarn](#yarn) + +## Npm + +- **Новый проект или существующий проект без Playwright:** + + Установите Playwright и Playwright-BDD: + ``` + npm i -D @playwright/test playwright-bdd + ``` + + Установите [браузеры](https://playwright.dev/docs/browsers) Playwright: + ``` + npx playwright install + ``` + +- **Существующий проект с Playwright:** + + Установите только Playwright-BDD: + ``` + npm i -D playwright-bdd + ``` + +Теперь вы можете начать [писать BDD тесты](ru/getting-started/write-first-test.md). + +## Pnpm + +- **Новый проект или существующий проект без Playwright:** + + Установите Playwright и Playwright-BDD: + ``` + pnpm i -D @playwright/test playwright-bdd + ``` + + Установите [браузеры](https://playwright.dev/docs/browsers) Playwright: + ``` + pnpm playwright install + ``` + +- **Существующий проект с Playwright:** + + Установите только Playwright-BDD: + ``` + pnpm i -D playwright-bdd + ``` + +Теперь вы можете начать [писать BDD тесты](ru/getting-started/write-first-test.md). + +## Yarn + +**Важно**: Для [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp) вам нужно добавить эти строки в `.yarnrc.yml`: + +```yml +packageExtensions: + playwright-bdd@*: + dependencies: + playwright: "*" + playwright-core: "*" +``` + +Затем продолжите с установкой пакетов. + +- **Новый проект или существующий проект без Playwright:** + + Установите Playwright и Playwright-BDD: + ``` + yarn add -D @playwright/test playwright-bdd + ``` + + Установите [браузеры](https://playwright.dev/docs/browsers) Playwright: + ``` + yarn playwright install + ``` + +- **Существующий проект с Playwright:** + + Установите только Playwright-BDD: + ``` + yarn add -D playwright-bdd + ``` + +Теперь вы можете начать [писать BDD тесты](ru/getting-started/write-first-test.md). diff --git a/docs/ru/getting-started/write-first-test.md b/docs/ru/getting-started/write-first-test.md new file mode 100644 index 00000000..9d0606f6 --- /dev/null +++ b/docs/ru/getting-started/write-first-test.md @@ -0,0 +1,123 @@ +# Напишите свой первый BDD тест + +Следуйте шагам ниже, чтобы создать и запустить ваш первый BDD тест с Playwright-BDD. + +?> Это руководство использует JavaScript для простоты, но вы можете использовать TypeScript также. + +### Шаг 1: Создайте файл конфигурации + +Создайте следующий `playwright.config.js` в корне проекта: + +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'sample.feature', + steps: 'steps.js', +}); + +export default defineConfig({ + testDir, + reporter: 'html', +}); +``` + +### Шаг 2: Создайте файл фичи + +Создайте файл фичи с именем `sample.feature`: + +```gherkin +Feature: Playwright site + + Scenario: Check get started link + Given I am on home page + When I click link "Get started" + Then I see in title "Installation" +``` + +### Шаг 3: Реализуйте шаги + +Реализуйте шаги в `steps.js`: + +```ts +import { expect } from '@playwright/test'; +import { createBdd } from 'playwright-bdd'; + +const { Given, When, Then } = createBdd(); + +Given('I am on home page', async ({ page }) => { + await page.goto('https://playwright.dev'); +}); + +When('I click link {string}', async ({ page }, name) => { + await page.getByRole('link', { name }).click(); +}); + +Then('I see in title {string}', async ({ page }, keyword) => { + await expect(page).toHaveTitle(new RegExp(keyword)); +}); +``` + +> Существуют альтернативные способы определения шагов: [Декораторы](ru/writing-steps/decorators.md) и [синтаксис в стиле Cucumber](ru/writing-steps/cucumber-style.md). + +### Шаг 4: Запустите тесты + +Сгенерируйте и запустите тесты: + +``` +npx bddgen && npx playwright test +``` + +Команда для **Yarn** +``` +yarn bddgen && yarn playwright test +``` + +Команда для **pnpm**: +``` +pnpm bddgen && pnpm playwright test +``` + +Вывод: + +``` +Running 1 test using 1 worker +1 passed (2.0s) + +To open the last HTML report, run: + +npx playwright show-report +``` + +HTML отчет: + +![Playwright HTML report](./../../getting-started/_media/playwright-report.png ':size=70%') + +### Шаг 5: Проверьте сгенерированные тесты (опционально) + +Проверьте директорию `.features-gen`, чтобы увидеть, как выглядят сгенерированные тесты. +Вы увидите что-то вроде этого: + +```js +// Generated from: sample.feature +import { test } from 'playwright-bdd'; + +test.describe('Playwright site', () => { + + test('Check get started link', async ({ Given, When, Then }) => { + await Given('I am on home page'); + await When('I click link "Get started"'); + await Then('I see in title "Installation"'); + }); + +}); +``` + +?> Вот полностью рабочий пример проекта Playwright-BDD: [playwright-bdd-example](https://github.com/vitalets/playwright-bdd-example). + +> Не забудьте [игнорировать сгенерированные файлы в git](ru/guides/ignore-generated-files.md). + +!> Если ваш проект использует [ES Modules](https://nodejs.org/api/esm.html), пожалуйста, ознакомьтесь с [конфигурацией ESM](ru/configuration/esm.md). + + diff --git a/docs/ru/guides/component-tests.md b/docs/ru/guides/component-tests.md new file mode 100644 index 00000000..47c17d42 --- /dev/null +++ b/docs/ru/guides/component-tests.md @@ -0,0 +1,107 @@ +# Компонентные тесты + +!> Не поддерживается + +Хотя компонентные тесты работают в простых случаях с Playwright-BDD, на самом деле эта функция не применима в реальных проектах. + +Есть два основных ограничения: + +1. Все компоненты, используемые в шагах, должны быть зарегистрированы и собраны для клиентской стороны. В Node.js они заменяются ссылочными объектами Playwright. +2. Все не-JS импорты (например, CSS или изображения) должны быть удалены из шагов, так как Node.js не может их обработать. + +Вы можете найти больше деталей в [#331](https://github.com/vitalets/playwright-bdd/issues/331) и [playwright#22302](https://github.com/microsoft/playwright/issues/22302). + +?> **Альтернативное решение:** подавайте вариации компонентов через [Storybook](https://storybook.js.org/) и запускайте тесты Playwright-BDD на них. + + diff --git a/docs/ru/guides/debugging.md b/docs/ru/guides/debugging.md new file mode 100644 index 00000000..e4885347 --- /dev/null +++ b/docs/ru/guides/debugging.md @@ -0,0 +1,25 @@ +# Отладка + +Вы можете использовать любые [методы отладки Playwright](https://playwright.dev/docs/debug) для BDD тестов. + +## Запуск тестов с флагом `--debug` + +Эта команда открывает браузер и позволяет выполнять пошаговую оценку: + +``` +npx bddgen && npx playwright test --debug +``` + +Пример скриншота: + +![debug-flag](./../../guides/_media/debug-flag.png) + +## Запуск тестов с флагом `--ui` + +Эта команда запускает BDD тесты в UI режиме: + +``` +npx bddgen && npx playwright test --ui +``` + +Подробнее в [UI режиме](guides/ui-mode.md). diff --git a/docs/ru/guides/env-variables.md b/docs/ru/guides/env-variables.md new file mode 100644 index 00000000..9ae89dc9 --- /dev/null +++ b/docs/ru/guides/env-variables.md @@ -0,0 +1,15 @@ +# Env variables + +To pass environment variables to both Playwright and Playwright-BDD, follow these steps: + +1. Install the `cross-env` package: + ``` + npm install -D cross-env + ``` + +2. Use the `cross-env-shell` command to set environment variables and run your tests: + ``` + npx cross-env-shell GREETING=hello "npx bddgen && npx playwright test" + ``` + +For more details, refer to the [cross-env documentation](https://github.com/kentcdodds/cross-env?tab=readme-ov-file#cross-env-vs-cross-env-shell). \ No newline at end of file diff --git a/docs/ru/guides/env-vars.md b/docs/ru/guides/env-vars.md new file mode 100644 index 00000000..332fa27f --- /dev/null +++ b/docs/ru/guides/env-vars.md @@ -0,0 +1,62 @@ +# Переменные окружения + +Вы можете использовать переменные окружения внутри определений шагов: +```js +When('I log in', async ({ page }) => { + await page.getByRole('textbox', { name: 'Username' }).fill(process.env.USERNAME); + await page.getByRole('textbox', { name: 'Password' }).fill(process.env.PASSWORD); + await page.getByRole('button', { name: 'Log in' }).click(); +}); +``` + +Фактические значения могут быть предоставлены через файл `.env`, импортированный в `playwright.config.ts` с помощью пакета [dotenv](https://github.com/motdotla/dotenv): + +``` +# .env +USERNAME=foo +PASSWORD=bar +``` + +```ts +// playwright.config.ts + +import { defineConfig, devices } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +import 'dotenv/config'; // <-- заполнить переменные окружения из .env + +const testDir = defineBddConfig({ + // ... +}); + +export default defineConfig({ + // ... +}); +``` + +Альтернативно, вы можете передать переменные окружения напрямую в CLI команду. +Важный аспект - как правильно это сделать. + +Следующее **не будет работать**: +```sh +USERNAME=foo npx bddgen && npx playwright test +``` + +Проблема в том, что `USERNAME` передается в `npx bddgen`, но не в `npx playwright test`. + +Самый простой способ исправить это - поместить всю команду в npm скрипт в `package.json`: +```diff +"scripts": { ++ "test": "npx bddgen && npx playwright test", +}, +``` +А затем запустить как: +```sh +USERNAME=foo npm test +``` + +Или вы можете предоставить переменные окружения для всей команды с помощью пакета [cross-env](https://github.com/kentcdodds/cross-env): + +```sh +npx cross-env-shell USERNAME=foo "npx bddgen && npx playwright test" +``` diff --git a/docs/ru/guides/fix-with-ai.md b/docs/ru/guides/fix-with-ai.md new file mode 100644 index 00000000..42d67335 --- /dev/null +++ b/docs/ru/guides/fix-with-ai.md @@ -0,0 +1,140 @@ +# Исправление с помощью AI + +> Это **экспериментальная** функция, не стесняйтесь делиться вашими отзывами в [issues](https://github.com/vitalets/playwright-bdd/issues). + +Playwright-BDD **v8.1.0** представил новую функцию под названием **Fix with AI**. Она помогает быстро исправлять падающие тесты с помощью предложений AI. + +Когда тест падает, Playwright-BDD предварительно генерирует AI промпт и прикрепляет его к отчету. +Вы можете скопировать этот промпт в ваш любимый AI чат и получить предложения о том, как исправить тест. + +Промпт содержит релевантный контекст теста: + +- сообщение об ошибке +- шаги сценария +- фрагмент кода теста +- [ARIA снимок](https://playwright.dev/docs/aria-snapshots) страницы + +Пример прикрепленного промпта: + +![Prompt attachment](./../../guides/_media/prompt-attachment.png) + +
+ Шаблон промпта: + +``` +You are an expert in Playwright BDD testing. +Fix the error in the BDD scenario. + +- Provide response as a diff highlighted code snippet. +- First, try to fix the test by adjusting Gherkin steps parameters. +- If the test is not fixable by Gherkin, try to modify the code snippet. +- Strictly rely on the ARIA snapshot of the page. +- Avoid adding any new code. +- Avoid adding comments to the code. +- Avoid changing the test logic. +- Use only role-based locators: getByRole, getByLabel, etc. +- Add a concise note about applied changes. +- If the test may be correct and there is a bug in the page, note it. + +Failing gherkin scenario: + +Scenario: {scenarioName} +{steps} + +Error details: +{error} + +{snippet} + +ARIA snapshot of the page: + +{ariaSnapshot} +``` + +
+ +## Как включить + +1. Убедитесь, что у вас **Playwright v1.49** или новее. Функция Fix with AI требует доступности [ARIA-снимков](https://playwright.dev/docs/release-notes#aria-snapshots). + +2. Убедитесь, что у вас **Playwright-BDD v8.1.0** или новее + +3. Добавьте секцию `aiFix` в BDD конфиг: + ```js + const testDir = defineBddConfig({ + aiFix: { + promptAttachment: true, + }, + // ...other options + }); + ``` + +Вот и все. Теперь вы можете запустить падающий тест и проверить HTML отчеты. + +### Playwright HTML отчет + +В Playwright HTML отчете вы можете развернуть вложение и скопировать промпт, нажав на маленькую кнопку в правом верхнем углу: + +![Copying prompt in the Playwright HTML report](./../../guides/_media/pw-html-report-prompt-copy.png) + +### Cucumber HTML отчет + +В Cucumber HTML отчете есть дополнительные элементы управления, которые помогают скопировать промпт в буфер обмена и открыть ChatGPT: + +![Copying prompt in the Cucumber HTML report](./../../guides/_media/cucumber-html-report-prompt-copy.png) + +## Пример ответа (ChatGPT) + +Вот пример ответа от ChatGPT, который исправляет тест: + +![ChatGPT fix](./../../guides/_media/chatgpt-fix.png) + +## Настройка промпта + +Вы можете настроить шаблон промпта, чтобы получить лучшие результаты для вашего проекта: + +```js +const testDir = defineBddConfig({ + aiFix: { + promptAttachment: true, + promptTemplate: 'my custom prompt' + }, + // ...other options +}); +``` + +Ознакомьтесь с [промптом по умолчанию](https://github.com/vitalets/playwright-bdd/blob/main/src/ai/promptTemplate.ts) для вдохновения и списка доступных плейсхолдеров: + +- `{scenarioName}` +- `{steps}` +- `{error}` +- `{snippet}` +- `{ariaSnapshot}` + +?> Если вы получили отличные результаты с вашим пользовательским промптом, мы приглашаем вас поделиться им с сообществом! + +## Использование не-дефолтной страницы + +По умолчанию AI промпт захватывает ARIA снимок из встроенного экземпляра `page` Playwright. +Если вы используете сценарии с несколькими страницами, вы можете вручную установить экземпляр `page` для захвата ARIA снимка. +Для этого используйте BDD фикстуру `$prompt`: + +```js +When('I open a new tab', async ({ page, context, $prompt }) => { // <-- добавить фикстуру $prompt + const [newPage] = await Promise.all([ + context.waitForEvent('page'), + page.getByRole('link').click(), + ]); + $prompt.setPage(newPage); // <-- вызвать $prompt.setPage() для переключения страницы + await expect(newPage.getByRole('heading')).toContainText('Another page'); +}); +``` + +## Ограничения + +В некоторых случаях промпт не генерируется: + +- ошибка произошла в хуках, до инициализации фикстуры `page` +- ваши тесты не используют фикстуру `page` (например, API тестирование) + +Если вы ожидаете, что промпт будет прикреплен, но его нет, попробуйте воспроизвести ваш случай на [ветке "ai" playwright-bdd-example](https://github.com/vitalets/playwright-bdd-example/tree/ai) и откройте [issue](https://github.com/vitalets/playwright-bdd/issues). diff --git a/docs/ru/guides/ide-integration.md b/docs/ru/guides/ide-integration.md new file mode 100644 index 00000000..05b94a86 --- /dev/null +++ b/docs/ru/guides/ide-integration.md @@ -0,0 +1,44 @@ +# Интеграция с IDE + +Одна из целей Playwright-BDD - поддержка всех интеграций Playwright с IDE. Это главная причина для предварительной генерации тестовых файлов как обычных тестовых файлов Playwright. + +## VS Code + +### Официальное расширение Playwright +[Официальное расширение Playwright](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) поддерживается. Оно автоматически подхватывает сгенерированные тестовые файлы из директории `.features-gen`. Вы можете запускать/отлаживать тесты кликом: + + +### Cucumber (Gherkin) Full Support + +!> Если у вас включены оба расширения `Cucumber (Gherkin) Full Support` и `Official Cucumber extension`, VS Code не обрабатывает их корректно. Отключите одно из них. + +[Cucumber (Gherkin) Full Support](https://marketplace.visualstudio.com/items?itemName=alexkrechik.cucumberautocomplete) поддерживается. Вот рекомендуемая конфигурация в `.vscode/settings.json`: +```json +{ + "cucumberautocomplete.steps": ["features/steps/*.{ts,js}"], + "cucumberautocomplete.strictGherkinCompletion": false, + "cucumberautocomplete.strictGherkinValidation": false, + "cucumberautocomplete.smartSnippets": true, + "cucumberautocomplete.onTypeFormat": true, + "editor.quickSuggestions": { + "comments": false, + "strings": true, + "other": true + }, +} +``` +Вы получите автодополнение ваших шагов и переход к определению по клику в файлах фичей: + + +### Официальное расширение Cucumber + +!> Если у вас включены оба расширения `Cucumber (Gherkin) Full Support` и `Official Cucumber extension`, VS Code не обрабатывает их корректно. Отключите одно из них. + +[Официальное расширение Cucumber](https://marketplace.visualstudio.com/items?itemName=CucumberOpen.cucumber-official) поддерживается. Возможно, вам потребуется настроить расположение ваших фичей/шагов. + + +## Intellij IDE / Aqua +Встроенная поддержка Playwright работает как обычно: + + +> Возможно, вам потребуется установить путь к исполняемому файлу Playwright в [Run Configuration Template](https://www.jetbrains.com/help/idea/run-debug-configuration.html#change-template), чтобы избежать всплывающего окна перед каждым запуском теста diff --git a/docs/ru/guides/ignore-generated-files.md b/docs/ru/guides/ignore-generated-files.md new file mode 100644 index 00000000..89e76e79 --- /dev/null +++ b/docs/ru/guides/ignore-generated-files.md @@ -0,0 +1,15 @@ +# Игнорирование сгенерированных файлов + +Сгенерированные тестовые файлы должны быть в `.gitignore`, так как они создаются из файлов `.feature`. Обратите внимание, что Playwright хранит снимки рядом с тестовыми файлами, поэтому вместо игнорирования всей директории `.features-gen`, лучше игнорировать только файлы `*.spec.js`: +``` +**/.features-gen/**/*.spec.js +``` + +Другой вариант - установить [`snapshotPathTemplate`](https://playwright.dev/docs/api/class-testconfig#test-config-snapshot-path-template) в пользовательское расположение вне `.features-gen`. Например: +```ts +export default defineConfig({ + snapshotPathTemplate: + '__snapshots__/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}', + // ... +}); +``` diff --git a/docs/ru/guides/index.md b/docs/ru/guides/index.md new file mode 100644 index 00000000..92df9821 --- /dev/null +++ b/docs/ru/guides/index.md @@ -0,0 +1,14 @@ +# Руководства + + - [🤖 Исправление с помощью AI](guides/fix-with-ai.md) + - [Миграция на v7](guides/migration-v7.md) + - [Игнорирование сгенерированных файлов](guides/ignore-generated-files.md) + - [Отладка](guides/debugging.md) + - [UI режим](guides/ui-mode.md) + - [Переменные окружения](guides/env-vars.md) + - [Компонентные тесты](guides/component-tests.md) + - [Интеграция с IDE](guides/ide-integration.md) + - [Использование с Nx](guides/usage-with-nx.md) + - [Использование с Currents](guides/usage-with-currents.md) + - [Использование с SauceLabs](guides/usage-with-saucelabs.md) + - [Использование с BrowserStack](guides/usage-with-browserstack.md) diff --git a/docs/ru/guides/migration-v7.md b/docs/ru/guides/migration-v7.md new file mode 100644 index 00000000..e1aa35af --- /dev/null +++ b/docs/ru/guides/migration-v7.md @@ -0,0 +1,253 @@ +# Миграция на v7 + +Playwright-BDD **v7** представляет несколько значительных улучшений, в первую очередь **удаление зависимости от раннера Cucumber** ([#136](https://github.com/vitalets/playwright-bdd/issues/136)). Теперь фичи и шаги обрабатываются напрямую без вовлечения пакета `@cucumber/cucumber`, улучшая опыт разработки, производительность и будущую поддержку. Это руководство охватывает все изменения и необходимые действия. + +Руководство состоит из двух частей, в зависимости от стиля шагов, который вы используете: +1. Действия для **всех пользователей** +2. Дополнительные действия для **cucumber-style** + +## Все пользователи +Приведенные ниже действия относятся ко всем пользователям playwright-bdd. + +### Обновление пакетов +Удалите `@cucumber/cucumber` и обновите `playwright-bdd`: +``` +npm un @cucumber/cucumber +npm i -D playwright-bdd@latest +``` + +### Новая опция `steps` +Начиная с версии 7, используйте универсальную опцию `steps` вместо опций `require` и `import` из Cucumber. Эта опция `steps` - это glob паттерн, который ищет файлы определений шагов и может быть определен как строка или массив строк. В отличие от [Cucumber](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#finding-your-code), **нет местоположения по умолчанию** для этих файлов. Если ваша конфигурация полагается на местоположение по умолчанию, явно укажите путь `steps`. + +До: +```ts +const testDir = defineBddConfig({ + require: ['steps/*.ts'], + // или для ESM + // import: ['steps/*.ts'], +}); +``` +С v7: +```ts +const testDir = defineBddConfig({ + steps: 'steps/*.ts' +}); +``` + +> Опции `require` и `import` все еще разрешены в BDD конфигурации, но под капотом они конвертируются в `steps` и будут удалены в будущем. + +### Новая опция `features` +Используйте новую опцию `features` вместо `paths`. Поведение `features` такое же, за исключением того, что **нет местоположения по умолчанию** для файлов фичей, в отличие от [Cucumber](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#finding-your-features). Если ваша конфигурация полагается на местоположение по умолчанию, укажите путь к фичам явно. + +До: +```ts +const testDir = defineBddConfig({ + paths: ['features/*.feature'], +}); +``` +С v7: +```ts +const testDir = defineBddConfig({ + features: 'features/*.feature', +}); +``` + +> Опция `paths` все еще разрешена в BDD конфигурации, но под капотом она конвертируется в `features` и будет удалена в будущем. + +### Пропуск `importTestFrom` +С v7, опция конфигурации `importTestFrom` может быть опущена в большинстве случаев. Playwright-BDD теперь автоматически проверяет определения шагов и определяет оптимальный файл для импорта `test`. Единственное требование - включить файлы фикстур в паттерн опции `steps`. + +До: +```ts +const testDir = defineBddConfig({ + importTestFrom: 'steps/fixtures.ts', + steps: ['steps/steps.ts'], +}); +``` +С v7: +```ts +const testDir = defineBddConfig({ + steps: ['steps/steps.ts', 'steps/fixtures.ts'] +}); +// ИЛИ +const testDir = defineBddConfig({ + steps: 'steps/*.ts' +}); +``` + +> `importTestFrom` все еще можно использовать для специфических случаев. Если у вас есть такой случай, не стесняйтесь поделиться им в issues, и мы можем улучшить алгоритм. + +### Конфигурация Cucumber +До v7, если был файл `cucumber.js`, он загружался и объединялся с BDD конфигурацией. Теперь `cucumber.js` больше не загружается. Единственный источник опций - это `defineBddConfig()` в `playwright.config.ts`. + +> Если вам нужна опция Cucumber, которая не поддерживается, не стесняйтесь запросить её в [issues](https://github.com/vitalets/playwright-bdd/issues). + +### Сниппеты +До v7, вы могли настроить [сниппеты](https://github.com/cucumber/cucumber-js/blob/main/docs/snippets.md) через опции Cucumber `snippetInterface` / `snippetSyntax`. Теперь эти опции удалены из BDD конфигурации. Playwright-BDD автоматически определяет стиль ваших шагов (playwright-style / cucumber-style / decorators) и показывает правильный синтаксис для отсутствующих шагов. + +Пример сниппета в стиле Playwright: +``` +Some steps are without definition! + +// 1. Missing step definition for "features/one.feature:23:5" +Then('I see in title {string}', async ({}, arg: string) => { + // ... +}); + +Missing step definitions: 1. +Use snippets above to create them. +``` + +> Если у вас есть строгое требование для пользовательских сниппетов, не стесняйтесь открыть issue. + +### Пользовательские типы параметров +- `defineParameterType` должен импортироваться из `playwright-bdd` вместо `@cucumber/cucumber`. +- `defineParameterType` теперь поддерживается в шагах с декораторами! + +Пример: +```ts +import { defineParameterType } from 'playwright-bdd'; + +type Color = 'red' | 'blue' | 'yellow'; +defineParameterType({ + name: 'color', + regexp: /red|blue|yellow/, + transformer: (s) => s.toLowerCase() as Color, +}); + +Given('step with {color}', ({}, color: Color) => { ... }); +``` + +### ESM +ESM проекты могут быть выполнены без `--loader=ts-node/esm` (с Playwright 1.41). + +До: +``` +npx cross-env NODE_OPTIONS="--loader=ts-node/esm --no-warnings" bddgen && npx playwright test +``` +С v7: +``` +npx bddgen && npx playwright test +``` + +### DataTable +`DataTable` должен импортироваться из `playwright-bdd` вместо `@cucumber/cucumber`. + +До: +```ts +import { DataTable } from '@cucumber/cucumber'; +``` +С v7: +```ts +import { DataTable } from 'playwright-bdd'; +``` + +### Другие изменения +* Минимальная версия Playwright повышена до **v1.35** +* Минимальная версия Node.js повышена до **v18** + +## Действия для Cucumber-style +Шаги в стиле Cucumber требуют некоторых дополнительных действий из-за удаления `@cucumber/cucumber`. + +### Импорт Given / When / Then +До v7, `Given / When / Then` для cucumber-style импортировались напрямую из пакета `@cucumber/cucumber`. Теперь эти функции должны быть созданы из `createBdd()` аналогично шагам в стиле Playwright. Единственное отличие - вы должны передать дополнительную опцию (описана ниже). + +До: + +```ts +import { Given, When, Then } from '@cucumber/cucumber'; + +Given('I am on home page', async function () { + await this.page.goto('/'); +}); +``` +С v7: + +**fixtures.ts** +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +// определить простейший world (см. следующую секцию для подробностей) +type World = { page: Page }; + +export const test = base.extend<{ world: World }>({ + world: async ({ page }, use) => { + const world = { page }; + await use(world); + }, +}); + +export const { Given, When, Then } = createBdd(test, { + worldFixture: 'world' +}); +``` + +**steps.ts** +```ts +import { Given, When, Then } from './fixtures'; + +Given('I am on home page', async function () { + await this.page.goto('/'); +}); +``` + +> Ознакомьтесь с полным примером в стиле Cucumber в [examples/cucumber-style](https://github.com/vitalets/playwright-bdd/tree/main/examples/cucumber-style). + +### Cucumber world +С v7, нет встроенного `World`. Если вам нужен world для шагов в стиле cucumber, определите его с нуля как фикстуру Playwright. Вы не ограничены наследованием world от какого-либо базового класса. Затем передайте имя фикстуры world в `createBdd` и получите `Given / When / Then`, привязанные к этому world. + +Пример: + +1. **world.ts** - создать world + +```ts +import { Page, TestInfo } from '@playwright/test'; + +export class MyWorld { + constructor (public page: Page, testInfo: TestInfo) {} + + async openHomepage() { + await this.page.goto('/'); + } + + async clickLink(name: string) { + await this.page.getByRole('link', { name }).click(); + } +}; +``` + +2. **fixtures.ts** - обернуть world в фикстуру Playwright и привязать к `Given / When / Then` + +```ts +import { test as base, createBdd } from 'playwright-bdd'; +import { MyWorld } from './world'; + +export const test = base.extend<{ myWorld: MyWorld }>({ + myWorld: async ({ page }, use, testInfo) => use(new MyWorld(page, testInfo)); +}); + +export const { Given, When, Then } = createBdd(test, { + worldFixture: 'myWorld' // <- указать имя фикстуры world +}); +``` + +3. **steps.ts** - писать шаги используя world как `this` + +```ts +import { Given, When, Then } from './fixtures'; + +Given('I am on the home page', async function () { + await this.openHomepage() +}); + +When('I click link {string}', async function (text: string) { + await this.clickLink(text); +}); +``` + +> Ознакомьтесь с полным примером в стиле Cucumber в [examples/cucumber-style](https://github.com/vitalets/playwright-bdd/tree/main/examples/cucumber-style). + +### Могу ли я получить предыдущий BddWorld в v7? +Да. Предыдущий `BddWorld` извлечен в отдельный файл [bddWorld.ts](https://github.com/vitalets/playwright-bdd/blob/v7/test/bdd-world-extracted/steps/bddWorld.ts). Вы можете скопировать/вставить его и настроить позже под свои нужды. После копирования, ознакомьтесь с [fixtures.ts](https://github.com/vitalets/playwright-bdd/blob/v7/test/bdd-world-extracted/steps/fixtures.ts), чтобы увидеть, как инициализировать BddWorld в вашем коде. + +?> Если вы обнаружили какую-либо ошибку/отсутствующий пункт в этом руководстве, не стесняйтесь открыть [issue](https://github.com/vitalets/playwright-bdd/issues) на GitHub. diff --git a/docs/ru/guides/ui-mode.md b/docs/ru/guides/ui-mode.md new file mode 100644 index 00000000..b0d42a69 --- /dev/null +++ b/docs/ru/guides/ui-mode.md @@ -0,0 +1,22 @@ +# UI режим и отслеживание изменений + +Вы можете автоматически перегенерировать тестовые файлы при любом изменении в фичах или определениях шагов. Используйте [nodemon](https://github.com/remy/nodemon) для отслеживания директорий и вызова `npx bddgen`: +``` +npx nodemon -w ./features -w ./steps -e feature,js,ts --exec "npx bddgen" +``` + +Для отладки тестов в [UI режиме](https://playwright.dev/docs/test-ui-mode), запустите приведенную выше команду вместе с `npx playwright test --ui`. Вы можете использовать пакет [npm-run-all](https://github.com/mysticatea/npm-run-all) для этого. Пример `package.json`: + +```json +"scripts": { + "watch:bdd": "nodemon -w ./features -w ./steps -e feature,js,ts --exec \"npx bddgen\"", + "watch:pw": "playwright test --ui", + "watch": "run-p watch:*" +} +``` +Запуск: +```sh +npm run watch +``` + +![ui-mode](./../../guides/_media/ui-mode.png) diff --git a/docs/ru/guides/usage-with-browserstack.md b/docs/ru/guides/usage-with-browserstack.md new file mode 100644 index 00000000..0c33bc0c --- /dev/null +++ b/docs/ru/guides/usage-with-browserstack.md @@ -0,0 +1,54 @@ +# Использование с BrowserStack + +Вы можете запускать Playwright-BDD тесты в облаке на платформе [BrowserStack](https://www.browserstack.com/). + +#### 1. Установите `browserstack-node-sdk` +``` +npm i -D browserstack-node-sdk +``` + +#### 2. Настройте учетные данные BrowserStack +Создайте файл `browserstack.yml` в корне проекта и добавьте ваше имя пользователя и ключ доступа BrowserStack [username and access key](https://www.browserstack.com/accounts/settings): +```yaml +userName: YOUR_USERNAME +accessKey: YOUR_ACCESS_KEY +``` + +#### 3. Настройте браузеры +Добавьте [конфигурацию](https://www.browserstack.com/docs/automate/playwright/project-config) для метаданных сборки и браузеров для запуска ваших тестов: +```yaml +userName: YOUR_USERNAME +accessKey: YOUR_ACCESS_KEY + +projectName: playwright-bdd sample +buildName: my-build-name +buildIdentifier: '#${BUILD_NUMBER}' +platforms: + - os: Windows + osVersion: 11 + browserName: chrome + browserVersion: latest + playwrightConfigOptions: + name: chromium + - os: OS X + osVersion: Ventura + browserName: playwright-webkit + browserVersion: latest + playwrightConfigOptions: + name: osx + + # больше браузеров +``` + +#### 4. Запустите тесты + +Запустите тесты следующей командой: +``` +npx bddgen && npx browserstack-node-sdk playwright test +``` + +Проверьте результаты тестов в [дашборде BrowserStack](https://automate.browserstack.com/dashboard): + +![BrowserStack dashboard](./../../guides/_media/browserstack.png) + +> Вот [полностью рабочий пример с BrowserStack](https://github.com/vitalets/playwright-bdd-example/tree/browserstack). diff --git a/docs/ru/guides/usage-with-currents.md b/docs/ru/guides/usage-with-currents.md new file mode 100644 index 00000000..8dadf350 --- /dev/null +++ b/docs/ru/guides/usage-with-currents.md @@ -0,0 +1,64 @@ +# Использование с Currents + +Вы можете интегрировать Playwright-BDD тесты с дашбордом [Currents](https://currents.dev/). + +#### 1. [Зарегистрируйтесь](https://app.currents.dev/signup) в Currents и создайте новый проект +Обратитесь к [инструкции по настройке Playwright](https://docs.currents.dev/getting-started/playwright/you-first-playwright-run) в случае каких-либо проблем. + +#### 2. Установите зависимости +Выполните следующую команду для установки репортера Currents + Playwright: +```sh +npm i -D @currents/playwright +``` +Установите [dotenv](https://www.npmjs.com/package/dotenv) для управления учетными данными Currents: +```sh +npm i -D dotenv +``` + +#### 3. Настройте учетные данные +Создайте файл `.env` со следующими переменными: +``` +CURRENTS_RECORD_KEY=YOUR_RECORD_KEY # ключ записи из https://app.currents.dev +CURRENTS_PROJECT_ID=YOUR_PROJECT_ID # projectId из https://app.currents.dev +``` + +#### 4. Настройте конфигурацию Playwright + +В конфигурационном файле Playwright `playwright.config.ts` настройте репортер Currents: + +```ts +import 'dotenv/config'; +import { defineConfig, devices } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; +import { CurrentsConfig, currentsReporter } from '@currents/playwright'; + +const currentsConfig: CurrentsConfig = { + recordKey: process.env.CURRENTS_RECORD_KEY || '', + projectId: process.env.CURRENTS_PROJECT_ID || '', +}; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'features/steps/*.ts', +}); + +export default defineConfig({ + testDir, + reporter: [currentsReporter(currentsConfig)], + use: { + screenshot: 'on', + trace: 'on', + }, +}); +``` + +#### 5. Запустите тесты +``` +npx bddgen && npx playwright test +``` + +Проверьте результаты в [дашборде Currents](https://app.currents.dev/): + +![Currents dashboard](./../../guides/_media/currents.png) + +> Вот [полностью рабочий пример с Currents](https://github.com/vitalets/playwright-bdd-example/tree/currents). diff --git a/docs/ru/guides/usage-with-nx.md b/docs/ru/guides/usage-with-nx.md new file mode 100644 index 00000000..82359831 --- /dev/null +++ b/docs/ru/guides/usage-with-nx.md @@ -0,0 +1,84 @@ +# Использование с Nx + +Вы можете запускать Playwright-BDD тесты с [Nx](https://nx.dev) и плагином [@nx/playwright](https://nx.dev/nx-api/playwright). + +Представьте следующую структуру рабочего пространства: +``` +/app1 + /e2e + ... + project.json + playwright.config.ts +/app2 + /e2e + ... + project.json + playwright.config.ts +nx.json +``` + +Чтобы запустить e2e тесты внутри `app1` или `app2`, добавьте цели в `project.json` каждого приложения: +```json +{ + "targets": { + "bddgen": { + "command": "bddgen", + "options": { + "cwd": "{projectRoot}" + } + }, + "e2e": { + "executor": "@nx/playwright:playwright", + "dependsOn": ["bddgen"], + "options": { + "config": "{projectRoot}" + } + } + } +} +``` + +Теперь из корня рабочего пространства вы можете запустить: +```bash +npx nx e2e app1 +# или +npx nx e2e app2 +``` + +Чтобы запустить e2e тесты в **обоих** `app1` и `app2`: +```bash +npx nx run-many -t e2e -p app1 app2 +``` + +Если есть много проектов с одинаковой настройкой e2e, вы можете переместить настройки по умолчанию в `nx.json`: +```json +{ + "targetDefaults": { + "bddgen": { + "command": "bddgen", + "options": { + "cwd": "{projectRoot}" + } + }, + "e2e": { + "executor": "@nx/playwright:playwright", + "dependsOn": ["bddgen"], + "options": { + "config": "{projectRoot}" + } + } + } +} +``` + +Затем в `project.json` оставьте пустые цели: +```json +{ + "targets": { + "bddgen": {}, + "e2e": {} + } +} +``` + +Ознакомьтесь с [рабочим примером с Nx и playwright-bdd](https://github.com/vitalets/playwright-bdd-example/tree/nx). diff --git a/docs/ru/guides/usage-with-saucelabs.md b/docs/ru/guides/usage-with-saucelabs.md new file mode 100644 index 00000000..0a84346e --- /dev/null +++ b/docs/ru/guides/usage-with-saucelabs.md @@ -0,0 +1,112 @@ +# Использование с SauceLabs + +Вы можете запускать Playwright-BDD тесты в облаке на платформе [SauceLabs](https://saucelabs.com/). + +#### 1. Установите `saucectl` +``` +npm install -g saucectl +``` + +#### 2. Настройте учетные данные Sauce Labs +Предоставьте ваше имя пользователя и ключ доступа Sauce Labs [username and access key](https://app.saucelabs.com/user-settings) следующей команде: +``` +saucectl configure +``` + +#### 3. Добавьте конфигурацию Sauce Labs +Добавьте [конфигурацию](https://docs.saucelabs.com/web-apps/automated-testing/playwright/yaml/) Sauce Labs в `.sauce/config.yml`: +```yaml +apiVersion: v1alpha +kind: playwright +sauce: + region: us-west-1 + concurrency: 10 + metadata: + tags: [e2e, bdd] +playwright: + version: package.json +npm: + packages: + playwright-bdd: latest +rootDir: ./ +suites: + - name: 'Chromium Mac' + platformName: 'macOS 12' + screenResolution: '1440x900' + testMatch: ['.*.js'] + params: + browserName: 'chromium' + project: 'chromium' # Запускает проект, определенный в `playwright.config.js` +reporters: + spotlight: + enabled: true +``` + +#### 4. Настройте конфигурацию Playwright + +В конфигурационном файле Playwright `playwright.config.ts` проверьте переменную окружения `process.env.SAUCE_VM` и установите правильные опции репортера: + +```ts +import { defineConfig, devices } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'features/steps/*.ts', +}); + +export default defineConfig({ + testDir, + reporter: [ + process.env.SAUCE_VM // поместить отчет в __assets__ при запуске на SauceLabs + ? [ 'html', { open: 'never', outputFolder: '__assets__/html-report/', attachmentsBaseURL: './' } ] + : [ 'html', { open: 'never' } ], + ], + use: { + screenshot: 'on', + }, + projects: [ + { + name: 'chromium', // использовать имя проекта 'chromium', как определено в '.sauce/config.yml' + use: { ...devices['Desktop Chrome'] }, + }, + ], +}); +``` + +#### 5. Игнорируйте ненужные файлы при загрузке Sauce Labs +Добавьте файл `.sauceignore` со следующими путями: +``` +# This file instructs saucectl to not package any files mentioned here. + +.git/ +.github/ +.DS_Store +.hg/ +.vscode/ +.idea/ +.gitignore +.hgignore +.gitlab-ci.yml +.npmrc +\*.gif + +# Remove this to have node_modules uploaded with code +node_modules/ +``` + +#### 6. Запустите тесты +``` +npx bddgen && saucectl run +``` + +Проверьте результаты тестов в [дашборде Sauce Labs](https://app.saucelabs.com/dashboard/builds/vdc): + +![Sauce Labs dashboard](./../../guides/_media/saucelabs.png) + +> Вот [полностью рабочий пример с SauceLabs](https://github.com/vitalets/playwright-bdd-example/tree/saucelabs). + +## Ограничения + +* Ознакомьтесь с [ограничениями](https://docs.saucelabs.com/web-apps/automated-testing/playwright/limitations/) Sauce Labs для Playwright +* BDD шаги не отображаются в репортере Sauce Labs, см. [sauce-docs#3059](https://github.com/saucelabs/sauce-docs/issues/3059) diff --git a/docs/ru/index.md b/docs/ru/index.md new file mode 100644 index 00000000..addd9028 --- /dev/null +++ b/docs/ru/index.md @@ -0,0 +1,106 @@ + + +
+ + Playwright-BDD + +
+ +

Playwright-BDD

+ +
+ +Запуск [BDD](https://cucumber.io/docs/bdd/) тестов с помощью [Playwright](https://playwright.dev/) раннера + +
+ +## Быстрый старт +Перейдите к руководству [начало работы](ru/getting-started/index.md) или прочитайте ниже обзор проекта Playwright-BDD. + + +## Зачем BDD? +В эпоху AI вы можете вывести подход [BDD](https://cucumber.io/docs/bdd/) на новый уровень: + +- 🤖 **Генерация**: Отправьте бизнес-требования в AI чат и получите структурированные, читаемые фичи. +- ✅ **Валидация**: Уточните сгенерированные сценарии с помощью AI или коллег, сотрудничайте в виде текста вместо кода. +- 🛠 **Автоматизация**: [Используйте существующие шаги](ru/writing-features/chatgpt.md) для запуска тестов и предотвращения роста кодовой базы. + +## Почему Playwright раннер? + +И [Playwright](https://playwright.dev/), и [CucumberJS](https://github.com/cucumber/cucumber-js) имеют свои собственные раннеры. Вы можете использовать раннер CucumberJS с [Playwright как библиотекой](https://playwright.dev/docs/library) для выполнения BDD сценариев. Этот пакет предлагает **альтернативу**: преобразует BDD сценарии в тестовые файлы и запускает их напрямую с помощью Playwright. Вы получаете все преимущества Playwright раннера: + +- автоматическая инициализация и очистка браузера +- автоматический захват скриншотов, видео и трассировок +- параллелизация с шардингом +- автоматическое ожидание элементов страницы +- встроенное визуальное сравнение +- мощь фикстур Playwright +- [...и многое другое](https://playwright.dev/docs/library#key-differences) + + +## Дополнительные возможности +Playwright-BDD расширяет Playwright с помощью BDD возможностей, предлагая: + +- 🔥 Расширенная система тегов [по пути](ru/writing-features/tags-from-path.md) и [специальные теги](ru/writing-features/special-tags.md) +- 🎩 [Декораторы шагов](ru/writing-steps/decorators.md) для методов классов +- 🎯 [Ограниченные по области видимости определения шагов](ru/writing-steps/scoped.md) +- ✨ [Экспорт шагов](ru/writing-features/chatgpt.md) для AI +- ♻️ [Переиспользуемые функции шагов](ru/writing-steps/reusing-step-fn.md) + +## Как работает Playwright-BDD +Типичная команда для запуска тестов с Playwright-BDD: +``` +npx bddgen && npx playwright test +``` + +### Фаза 1: Генерация тестов +Первая команда `npx bddgen` генерирует тестовые файлы из BDD feature файлов. Например: + +Из +```gherkin +Feature: Playwright Home Page + + Scenario: Check title + Given I am on Playwright home page + When I click link "Get started" + Then I see in title "Installation" +``` + +В +```js +import { test } from 'playwright-bdd'; + +test.describe('Playwright Home Page', () => { + + test('Check title', async ({ Given, When, Then }) => { + await Given('I am on Playwright home page'); + await When('I click link "Get started"'); + await Then('I see in title "Installation"'); + }); + +}); +``` + +### Фаза 2: Запуск тестов +Вторая команда `npx playwright test` запускает сгенерированные файлы с помощью Playwright раннера. +Определения шагов имеют доступ к Playwright API и фикстурам (например, `page`): + +```js +Given('I am on Playwright home page', async ({ page }) => { + await page.goto('https://playwright.dev'); +}); + +When('I click link {string}', async ({ page }, name) => { + await page.getByRole('link', { name }).click(); +}); + +Then('I see in title {string}', async ({ page }, text) => { + await expect(page).toHaveTitle(new RegExp(text)); +}); +``` + +HTML отчет показывает все сценарии и шаги: + +![Playwright html report](./../reporters/_media/pw-html-report.png) + +Перейдите к [руководству по установке](ru/getting-started/installation.md) и попробуйте сами. \ No newline at end of file diff --git a/docs/ru/pickles.md b/docs/ru/pickles.md new file mode 100644 index 00000000..4df0ee1f --- /dev/null +++ b/docs/ru/pickles.md @@ -0,0 +1,55 @@ + + +# Pickles + +Связь между Cucumber pickles и Gherkin сценариями довольно сложная, особенно когда есть background и examples. Разбивка ниже помогает это понять. + +Представьте следующий файл фичи: +```gherkin +Feature: feature 1 + + Background: + A + + Scenario: scenario 1 + B + + Scenario Outline: scenario 2 + C + + Examples: + C1 + C2 +``` + +Он производит 3 pickle, `astNodeIds` показаны в скобках: +``` +pickle 1 (scenario 1) + pickleStep 1.1 (A) + pickleStep 1.2 (B) + +pickle 2 (scenario 2, example row 1) + pickleStep 2.1 (A) + pickleStep 2.2 (C) + +pickle 3 (scenario 2, example row 2) + pickleStep 3.1 (A) + pickleStep 3.2 (C) +``` +Обратное отображение на файл фичи: +```gherkin +Feature: feature 1 + + Background: # referenced from: none + A # referenced from: pickleStep 1.1, pickleStep 2.1, pickleStep 3.1 + + Scenario: scenario 1 # referenced from: pickle 1 + B # referenced from: pickleStep 1.2 + + Scenario Outline: scenario 2 # referenced from: pickle 2, pickle 3 + C # referenced from: pickleStep 2.2, pickleStep 3.2 + + Examples: + C1 # referenced from: pickle 2 + C2 # referenced from: pickle 3 +``` diff --git a/docs/ru/reporters/allure.md b/docs/ru/reporters/allure.md new file mode 100644 index 00000000..11ff0a45 --- /dev/null +++ b/docs/ru/reporters/allure.md @@ -0,0 +1,39 @@ +# Репортер Allure + +Вы можете выводить результаты тестов с помощью репортера **allure-playwright** (не `allure-cucumberjs`). Следуйте инструкциям ниже: + +1. [Установите Allure](https://allurereport.org/docs/install/) + +2. [Установите Allure-Playwright](https://allurereport.org/docs/playwright/) + +3. Включите `allure-reporter` в конфигурации Playwright: + + ```js + import { defineConfig } from '@playwright/test'; + import { defineBddConfig } from 'playwright-bdd'; + + const testDir = defineBddConfig({ /* BDD config */ }); + + export default defineConfig({ + testDir, + reporter: 'allure-playwright', // <- включите репортер allure + }); + ``` + +Теперь запустите тесты как обычно: +``` +npx bddgen && npx playwright test +``` + +Пример файла фичи: +```gherkin +Feature: Playwright Home Page + + Scenario: Check title + Given I am on Playwright home page + When I click link "Get started" + Then I see in title "Installation" +``` + +Пример отчета: +![Allure report](./../../reporters/_media/allure-report.png) diff --git a/docs/ru/reporters/cucumber.md b/docs/ru/reporters/cucumber.md new file mode 100644 index 00000000..d3c836a6 --- /dev/null +++ b/docs/ru/reporters/cucumber.md @@ -0,0 +1,354 @@ +# Репортеры Cucumber + +Playwright-BDD предоставляет специальный адаптер для вывода результатов тестов с помощью [репортеров Cucumber (форматтеров)](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md). + +В настоящее время поддерживаются следующие репортеры: + +* [html](#html) +* [json](#json) +* [junit](#junit) +* [message](#message) +* [custom](#custom) + +#### Автоматические скриншоты / видео / трейсы +Playwright-BDD полностью поддерживает автоматическое прикрепление **скриншотов**, **видео** и **трейсов** ко всем отчетам Cucumber. Включите эти опции в [конфигурации Playwright](https://playwright.dev/docs/test-use-options#recording-options). + +
Пример HTML отчета с прикрепленным скриншотом, видео и трейсом + +![html report](./../../reporters/_media/html-report-attachments.png) + +
+ +#### Проекты + +Форматтеры Cucumber изначально не поддерживают [концепцию проектов](https://playwright.dev/docs/test-projects#introduction) в Playwright. Однако Playwright-BDD адаптирует результаты тестов для отображения проектов в отчете Cucumber. + +Итоговый вывод зависит от конкретного репортера. Например, в HTML репортере имя проекта добавляется в начало пути к файлу фичи: + +![html report](./../../reporters/_media/html-report-projects.png) + +
Пример playwright.config.ts с несколькими проектами: + +```ts +import { defineConfig, devices } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'features/steps/*.ts', +}); + +export default defineConfig({ + testDir, + reporter: [ + cucumberReporter('html', { outputFile: 'cucumber-report/index.html' }) + ], + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + ], +}); +``` + +
+ +## html + +Генерирует [Cucumber html](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#html) отчет. + +Настройте репортер в `playwright.config.js`: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'steps/*.ts', +}); + +export default defineConfig({ + testDir, + reporter: [ + cucumberReporter('html', { outputFile: 'cucumber-report/index.html' }), + ], +}); +``` + +
Пример report.html + +![html report](./../../reporters/_media/html-report.png) + +
+ +##### Опции репортера + +* **outputFile** `string` - Путь к выходному HTML файлу. +* **skipAttachments** `boolean | string[]` (по умолчанию: `false`) - Исключить вложения из отчета для уменьшения размера файла. Может быть boolean или массивом типов контента для пропуска. + * Используйте `image/png` для пропуска скриншотов Playwright. + * Используйте `video/webm` для пропуска видеозаписей Playwright. + * Используйте `application/zip` для пропуска файлов трейса Playwright. + + ```js + export default defineConfig({ + reporter: [ + cucumberReporter('html', { + outputFile: 'cucumber-report/index.html', + skipAttachments: [ 'video/webm', 'application/zip' ], + }), + ], + }); + ``` +* **externalAttachments** `boolean` - Сохранять вложения как отдельные файлы в директории `data` рядом с файлом отчета. Это может значительно уменьшить размер отчета. +* **attachmentsBaseURL** `string` - Отдельное расположение, куда загружаются вложения из поддиректории `data`. Нужно только когда вы загружаете отчет и данные отдельно в разные места. То же самое, что `attachmentsBaseURL` [HTML репортера](https://playwright.dev/docs/test-reporters#html-reporter) Playwright. + +#### Просмотрщик трейсов +Когда вы устанавливаете `externalAttachments: true`, HTML отчет Cucumber встраивает [просмотрщик трейсов](https://playwright.dev/docs/trace-viewer) Playwright: + +```js +export default defineConfig({ + reporter: [ + cucumberReporter('html', { + outputFile: 'cucumber-report/index.html', + externalAttachments: true, + }), + ], +}); +``` + +Чтобы просмотреть трейс по клику, вы должны открыть HTML отчет по схеме `http(s)://`, а не `file://`. Чтобы достичь этого на локальной машине, вы можете запустить HTTP сервер следующей командой: +``` +npx http-server ./cucumber-report -c-1 -a localhost -o index.html +``` + +![html report with trace](./../../reporters/_media/html-report-with-trace.png) + +Вы можете добавить эту команду в скрипты `package.json` для быстрого открытия отчета Cucumber: +```json +{ + "scripts": { + "report": "npx http-server ./cucumber-report -c-1 -a localhost -o index.html" + } +} +``` +Откройте отчет Cucumber: +``` +npm run report +``` + +## json +Генерирует [Cucumber json](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#json) отчет. + +Настройте репортер в `playwright.config.js`: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: ['features/*.feature'], + steps: ['steps/*.ts'], +}); + +export default defineConfig({ + testDir, + reporter: [ + cucumberReporter('json', { outputFile: 'cucumber-report/report.json' }), + ], +}); +``` + +
Пример report.json + +[json report](./../../reporters/_media/json-report.json ':include') + +
+ +##### Опции репортера + +* **outputFile** `string` - Путь к выходному JSON файлу. +* **addProjectToFeatureName** `boolean` - Если `true`, имя проекта будет добавлено в начало имени фичи, рекомендуется для запусков с несколькими проектами (по умолчанию: `false`). +* **addMetadata** `none | list | object` - Определяет форму метаданных для прикрепления к элементу фичи. В настоящее время прикрепляются свойства: `Project`, `Browser`. Полезно для сторонних репортеров. Пример метаданных `list`: + ```json + { + "keyword": "Feature", + "name": "feature one", + "uri": "features/sample.feature", + "metadata": [ + { "name": "Project", "value": "my project" }, + { "name": "Browser", "value": "firefox" } + ] + }, + ``` + +* **skipAttachments** `boolean | string[]` (по умолчанию: `false`) - См. [skipAttachments](#reporter-options) в HTML отчете. + +Вывод JSON репортера можно использовать для генерации некоторых сторонних отчетов. Ознакомьтесь с этими проектами: + +* [WasiqB/multiple-cucumber-html-reporter](https://github.com/WasiqB/multiple-cucumber-html-reporter) +* [gkushang/cucumber-html-reporter](https://github.com/gkushang/cucumber-html-reporter) + +## junit +Генерирует [Cucumber junit](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#junit) отчет. + +?> Для новых проектов рекомендуется использовать `junit-modern` вместо `junit`, все опции одинаковые. + +Настройте репортер в `playwright.config.js`: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: ['features/*.feature'], + steps: ['steps/*.ts'], +}); + +export default defineConfig({ + testDir, + reporter: [ + // для новых проектов + cucumberReporter('junit-modern', { + outputFile: 'cucumber-report/report.xml', + suiteName: 'my suite' + }), + // для старых проектов + cucumberReporter('junit', { + outputFile: 'cucumber-report/report.xml', + suiteName: 'my suite' + }), + ], +}); +``` + +
Пример report.xml + +[junit report](./../../reporters/_media/junit-report.xml ':include') + +
+ +##### Опции репортера + +* **outputFile** `string` - Путь к выходному XML файлу. +* **suiteName** `string` - Атрибут имени элемента `testsuite`. + +> Junit репортер не содержит вложений. + +## message +Генерирует [Cucumber message](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#message) отчет. + +Настройте репортер в `playwright.config.js`: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: ['features/*.feature'], + steps: ['steps/*.ts'], +}); + +export default defineConfig({ + testDir, + reporter: [ + cucumberReporter('message', { outputFile: 'cucumber-report/report.ndjson' }), + ], +}); +``` + +
Пример report.ndjson + +[message report](./../../reporters/_media/message-report.ndjson ':include') + +
+ +##### Опции репортера + +* **outputFile** `string` - Путь к выходному NDJSON файлу. +* **skipAttachments** `boolean | string[]` (по умолчанию: `false`) - См. [skipAttachments](#reporter-options) в HTML отчете. + +> Обратите внимание, что эти 4 [типа сообщений](https://github.com/cucumber/messages/blob/main/messages.md#envelope) пока не поддерживаются: +> - `parameterType` +> - `stepDefinition` +> - `undefinedParameterType` +> - `parseError` +> +> Если они требуются для вашего отчета, не стесняйтесь [открыть issue](https://github.com/vitalets/playwright-bdd/issues). + +## custom +Playwright-BDD поддерживает [пользовательские форматтеры Cucumber](https://github.com/cucumber/cucumber-js/blob/main/docs/custom_formatters.md). + +Создайте файл пользовательского репортера, например, `my-reporter.ts`: +```ts +import * as messages from '@cucumber/messages'; +import { Formatter, IFormatterOptions } from '@cucumber/cucumber'; + +export default class CustomFormatter extends Formatter { + constructor(options: IFormatterOptions) { + super(options); + options.eventBroadcaster.on('envelope', (envelope: messages.Envelope) => { + console.log(JSON.stringify(envelope)); + }); + } +} +``` + +!> Обратите внимание, что опции конструктора `colorFns`, `snippetBuilder` и `supportCodeLibrary` передаются как фиктивные объекты. + +Настройте репортер в `playwright.config.js`: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'steps/*.ts', +}); + +export default defineConfig({ + testDir, + reporter: [ + cucumberReporter('./my-reporter.ts', { someKey: 'someValue' }), + ], +}); +``` + +Все опции, переданные в `cucumberReporter()`, будут доступны как `options.parsedArgvOptions`. + +## Слияние отчетов + +С версии Playwright **1.37** есть команда [merge-reports](https://playwright.dev/docs/test-sharding#merging-reports-from-multiple-shards), которая выводит объединенный отчет из нескольких шардов. Playwright-BDD также поддерживает эту функцию и может создавать объединенные отчеты Cucumber. + +Добавьте конфигурацию в `playwright.config.ts`: +```ts +import { defineConfig } from '@playwright/test'; +import { defineBddConfig, cucumberReporter } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + features: 'features/*.feature', + steps: 'features/*.ts', +}); + +// Различайте запуски шардов от обычных локальных запусков и запуска merge-reports +const isShardRun = process.argv.some((a) => a.startsWith('--shard')); + +export default defineConfig({ + testDir, + reporter: isShardRun + ? 'blob' // на шарде выводить Blob отчет + : [ cucumberReporter('html', { outputFile: 'report.html' }) ], +}); +``` + +Запустите тесты на шарде: +``` +npx bddgen && npx playwright test --shard 1/2 +npx bddgen && npx playwright test --shard 2/2 +``` + +Объедините отчеты (важно передать опцию `--config`, указывающую на `playwright.config.ts`): +``` +npx playwright merge-reports --config playwright.config.ts ./blob-report +``` diff --git a/docs/ru/reporters/index.md b/docs/ru/reporters/index.md new file mode 100644 index 00000000..853ab962 --- /dev/null +++ b/docs/ru/reporters/index.md @@ -0,0 +1,8 @@ +# Репортеры + +Playwright-BDD предоставляет множество опций для отчетности: +- нативные [репортеры Playwright](reporters/playwright.md) +- [репортеры Cucumber](reporters/cucumber.md) +- сторонние репортеры, такие как [Allure](reporters/allure.md) + + diff --git a/docs/ru/reporters/playwright.md b/docs/ru/reporters/playwright.md new file mode 100644 index 00000000..d1920b49 --- /dev/null +++ b/docs/ru/reporters/playwright.md @@ -0,0 +1,32 @@ +# Репортеры Playwright + +Все [репортеры Playwright](https://playwright.dev/docs/test-reporters) поддерживаются из коробки. Они менее адаптированы под BDD, но содержат все последние возможности отчетности Playwright. + +Пример включения HTML репортера Playwright: +```js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ /* BDD config */ }); + +export default defineConfig({ + testDir, + reporter: 'html', // <- определите репортер как обычно +}); +``` + +Файл фичи: +```gherkin +Feature: Playwright Home Page + + Scenario: Check title + Given I am on Playwright home page + When I click link "Get started" + Then I see in title "Installation" +``` + +Отчет: +![Playwright html report](./../../reporters/_media/pw-html-report.png) + +Если вам нужны более адаптированные под BDD отчеты, ознакомьтесь с [репортерами Cucumber](reporters/cucumber.md). + diff --git a/docs/ru/sponsors.md b/docs/ru/sponsors.md new file mode 100644 index 00000000..da1beab3 --- /dev/null +++ b/docs/ru/sponsors.md @@ -0,0 +1,22 @@ +# Спонсируйте Playwright-BDD ❤️ + +Playwright-BDD здесь, чтобы сделать ваше BDD тестирование гладким и супер-эффективным с магией Playwright. Независимо от того, опытный ли вы тестировщик или только погружаетесь в мир BDD, мы вас поддержим! + +Но эй, создание и поддержка открытого проекта требует времени, усилий и хорошей дозы кофеина. ☕ Вот где вы пригодитесь! Ваше спонсорство помогает поддерживать свет, код течет, и баги раздавливаются. Это также питает миссию сделать BDD тестирование более доступным для всех. + +География Playwright-BDD: + +![Users of Playwright-BDD](./../../_media/map.png) + +## Почему спонсировать? +- **Больше функций, быстрее!** Ваша поддержка позволяет сосредоточиться на выпуске крутых вещей. +- **Любовь сообщества.** Продолжать расти и поддерживать тестировщиков по всему миру. +- **Будьте частью чего-то потрясающего.** Серьезно, это отличное чувство отдавать открытому источнику! + +💖 **[Стать спонсором](https://github.com/sponsors/vitalets)** 💖 + +## Наши удивительные спонсоры 🌟 + +Огромное спасибо нашим текущим спонсорам за их неоценимую поддержку! 🫶 + +User avatar: Currents.devUser avatar: User avatar: User avatar: Arturs LeščinskisUser avatar: User avatar: User avatar: Francesco BorzìUser avatar: Adam Banko diff --git a/docs/ru/writing-features/auto-formatting.md b/docs/ru/writing-features/auto-formatting.md new file mode 100644 index 00000000..c40c77a5 --- /dev/null +++ b/docs/ru/writing-features/auto-formatting.md @@ -0,0 +1,18 @@ +# Автоформатирование файлов фич + +Написание файлов фич более удобно с автоформатированием. Особенно когда речь идет о таблицах данных. + +Ознакомьтесь с форматтером [Prettier](https://prettier.io/) + расширением для IDE + [prettier-plugin-gherkin](https://github.com/mapado/prettier-plugin-gherkin?tab=readme-ov-file). + +Вот пример конфигурации Prettier `prettier.config.mjs`: + +```js +export default { + plugins: ['prettier-plugin-gherkin'], + // ...другие опции prettier +}; +``` + +Как это работает в VS Code: + +[auto-formatting](./../../writing-features/_media/auto-formatting.mp4 ':include') diff --git a/docs/ru/writing-features/chatgpt.md b/docs/ru/writing-features/chatgpt.md new file mode 100644 index 00000000..a60271d3 --- /dev/null +++ b/docs/ru/writing-features/chatgpt.md @@ -0,0 +1,134 @@ +# Использование ChatGPT +[ChatGPT](https://chat.openai.com) может написать BDD сценарии за вас! +Все, что вам нужно, это описать пользовательскую историю и предоставить определения шагов. + +* Для пользовательской истории вы можете просто использовать общие фразы, описывающие функцию +* Для определений шагов вы можете использовать [`bddgen export`](ru/cli.md#bddgen-export), которая выводит список всех шагов + +**Пример:** + +Представьте, что у вас есть простое [Todo приложение](https://demo.playwright.dev/todomvc/#/) и вы хотите покрыть его BDD тестами, написанными ChatGPT и выполняемыми Playwright. + +Сначала вам нужно написать определения шагов: + +> Мы по-прежнему пишем определения шагов вручную, чтобы получить надежные локаторы, но в будущем AI сможет генерировать их также + +```ts +import { createBdd } from 'playwright-bdd'; + +const { Given, When, Then } = createBdd(test); + +Given('I am on todo page', async ({ page }) => { + await page.goto('https://demo.playwright.dev/todomvc/'); +}); + +When('I add todo {string}', async ({ page }, text: string) => { + await page.locator('input.new-todo').fill(text); + await page.locator('input.new-todo').press('Enter'); +}); + +When('I remove todo {string}', async ({ page }, text: string) => { + const todo = page.getByTestId('todo-item').filter({ hasText: text }); + await todo.hover(); + await todo.getByRole('button', { name: 'Delete' }).click(); +}); + +Then('visible todos count is {int}', async ({ page }, count: number) => { + await expect(page.getByTestId('todo-item')).toHaveCount(count); +}); +``` +Теперь вы можете извлечь все доступные паттерны шагов с помощью `bddgen export`: +``` +$ bddgen export + +List of all steps found by config: playwright.config.ts + +* Given I am on todo page +* When I add todo {string} +* When I remove todo {string} +* Then visible todos count is {int} +``` + +И затем использовать следующий **шаблон промпта для ChatGPT**: +``` +Generate BDD scenarios in Gherkin for the following user story: + +{user story description} + +Format output as a single gherkin file. +Include user story text in the file. +Use Background for common steps. +Use "And" keyword for repeated "Given" / "When" / "Then". +Strictly use only the following step definitions: + +{steps list from bddgen export} +``` + +> Не стесняйтесь улучшать этот шаблон и делиться результатами + +Заполненный промпт для Todo приложения: +``` +Generate BDD scenarios for the following user story: + +As a user I want to add and remove todo items in todo list app. + +Format output as a single gherkin file. +Include user story text in the file. +Use Background for common steps. +Use "And" keyword for repeated "Given" / "When" / "Then". +Strictly use only the following step definitions: + +* Given I am on todo page +* When I add todo {string} +* When I remove todo {string} +* Then visible todos count is {int} +``` + +Вывод ChatGPT: +```gherkin +Feature: Adding and Removing Todo Items + + As a user + I want to add and remove todo items in a todo list app + So that I can manage my tasks effectively + + Background: + Given I am on todo page + + Scenario: Add a new todo and remove it + When I add todo "Buy groceries" + And I remove todo "Buy groceries" + Then visible todos count is 0 + + Scenario: Add multiple todos and remove one + When I add todo "Buy groceries" + And I add todo "Go to the gym" + And I add todo "Read a book" + And I remove todo "Go to the gym" + Then visible todos count is 2 + + Scenario: Add and remove multiple todos + When I add todo "Buy groceries" + And I add todo "Go to the gym" + And I add todo "Read a book" + And I remove todo "Buy groceries" + And I remove todo "Go to the gym" + Then visible todos count is 1 + + Scenario: Add multiple todos and remove all + When I add todo "Buy groceries" + And I add todo "Go to the gym" + And I add todo "Read a book" + And I remove todo "Buy groceries" + And I remove todo "Go to the gym" + And I remove todo "Read a book" + Then visible todos count is 0 +``` + +Теперь вы можете сохранить этот файл `.feature` и запустить тесты: +``` +npx bddgen && npx playwright test +``` + +Html отчет: + diff --git a/docs/ru/writing-features/customize-examples-title.md b/docs/ru/writing-features/customize-examples-title.md new file mode 100644 index 00000000..10f99dba --- /dev/null +++ b/docs/ru/writing-features/customize-examples-title.md @@ -0,0 +1,90 @@ +# Настройка заголовков примеров +По умолчанию каждая строка примера из `Scenario Outline` преобразуется в тест с заголовком `Example #{index}`. +Это может быть ненадежным для репортеров, которые отслеживают историю тестов, потому что при каждой вставке или удалении строк заголовки тестов будут смещаться. + +Существует три способа установить согласованный заголовок для примеров. + +#### 1. Использовать имя сценария как шаблон +Вы можете добавить имена столбцов вроде `` в имя сценария. В этом случае имя сценария будет использоваться как шаблон заголовка для сгенерированных примеров. + +!> Обратите внимание, что сгенерированные заголовки должны быть **уникальными** в пределах сценария, иначе Playwright выдаст ошибку. + +Пример: +```gherkin +Feature: Calculator + + Scenario Outline: Multiply by two + Given value is + When multiply by two + Then result is + + Examples: + | value | result | + | 1 | 2 | + | 2 | 4 | +``` + +Сгенерированный тестовый файл: +```js +test.describe(`Calculator`, () => { + + test.describe(`Multiply by two`, () => { + + test(`Multiply 1 by two`, async ({ Given, When, Then }) => { + await Given(`value is 1`); + await When(`multiply by two`); + await Then(`result is 2`); + }); + + test(`Multiply 2 by two`, async ({ Given, When, Then }) => { + await Given(`value is 2`); + await When(`multiply by two`); + await Then(`result is 4`); + }); + + }); +}); +``` + +#### 2. Использовать специальный синтаксис комментария +Вы можете предоставить свой собственный фиксированный формат заголовка, добавив специальный комментарий прямо над `Examples`. +Комментарий должен начинаться с `# title-format:` и может ссылаться на имена столбцов как ``. Например: +```gherkin +Feature: Calculator + + Scenario Outline: Multiply by two + Given value is + When multiply by two + Then result is + + # title-format: check + Examples: + | value | result | + | 1 | 2 | + | 2 | 4 | +``` + +Сгенерированный тестовый файл: +```js +test.describe(`Calculator`, () => { + + test.describe(`Multiply by two`, () => { + + test(`check 1`, async ({ Given, When, Then }) => { + await Given(`value is 1`); + await When(`multiply by two`); + await Then(`result is 2`); + }); + + test(`check 2`, async ({ Given, When, Then }) => { + await Given(`value is 2`); + await When(`multiply by two`); + await Then(`result is 4`); + }); + + }); +}); +``` + +#### 3. Использовать опцию конфигурации +Вы можете установить опцию конфигурации [examplesTitleFormat](ru/configuration/options.md#examplestitleformat) для определения глобального шаблона заголовков примеров. diff --git a/docs/ru/writing-features/i18n.md b/docs/ru/writing-features/i18n.md new file mode 100644 index 00000000..1516aae4 --- /dev/null +++ b/docs/ru/writing-features/i18n.md @@ -0,0 +1,24 @@ +# Локализация +Вы можете писать фичи на любом из [поддерживаемых Cucumber языков](https://cucumber.io/docs/gherkin/languages/). Язык может быть установлен глобально в конфигурации: + +```ts +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + language: 'es', + // другая конфигурация +}); +``` + +Или в конкретном файле фичи через директиву `# language`: + +```gherkin +# language: es +Característica: Sitio de Playwright + + Escenario: Verificar título + Dado que abro la url "https://playwright.dev" + Cuando hago clic en el enlace "Get started" + Entonces veo en el título "Playwright" +``` + diff --git a/docs/ru/writing-features/index.md b/docs/ru/writing-features/index.md new file mode 100644 index 00000000..1417312e --- /dev/null +++ b/docs/ru/writing-features/index.md @@ -0,0 +1,25 @@ +# Написание фич +Пишите фичи в файлах `*.feature` используя [синтаксис Gherkin](https://cucumber.io/docs/gherkin/reference/#keywords). Поддерживаются все ключевые слова. + +Пример `sample.feature`: + +```gherkin +@desktop +Feature: Playwright site + + @jira:123 + Scenario: Check title + Given I open url "https://playwright.dev" + When I click link "Get started" + Then I see in title "Playwright" +``` + +Теги позволяют запускать подмножество тестов, используя опцию `--tags` с [выражением тегов](https://cucumber.io/docs/cucumber/api/?lang=javascript#tag-expressions): +``` +npx bddgen --tags "@desktop and not @slow" && npx playwright test +``` + +?> С версии Playwright **1.42** теги Gherkin отображаются на [теги Playwright](https://playwright.dev/docs/test-annotations#tag-tests) + +Вы также можете [получить доступ к тегам внутри определений шагов](ru/writing-steps/bdd-fixtures.md#tags). + diff --git a/docs/ru/writing-features/special-tags.md b/docs/ru/writing-features/special-tags.md new file mode 100644 index 00000000..1b2032d3 --- /dev/null +++ b/docs/ru/writing-features/special-tags.md @@ -0,0 +1,113 @@ +# Специальные теги + +Существуют некоторые специальные теги для улучшения опыта тестирования. + +## @only +Используйте тег `@only` для запуска отдельной фичи или сценария: +```gherkin +@only +Feature: Playwright site + + @only + Scenario: Check title + Given I open url "https://playwright.dev" +``` + +## @skip / @fixme +Используйте тег `@skip` (или `@fixme`) для пропуска конкретной фичи или сценария: +```gherkin +@skip +Feature: Playwright site + + @skip + Scenario: Check title + Given I open url "https://playwright.dev" +``` + +Для условного пропуска сценария используйте [$test и $tags фикстуры](ru/writing-steps/bdd-fixtures.md#test-and-testinfo). + +## @fail +Используйте тег `@fail` для обозначения фичи или сценария как [падающего](https://playwright.dev/docs/api/class-test#test-fail): +```gherkin +Feature: Playwright site + + @fail + Scenario: Check title + Given I open url "https://playwright.dev" +``` + +## @slow +Используйте тег `@slow` для обозначения фичи или сценария как [медленного](https://playwright.dev/docs/api/class-test#test-slow) (timeout x 3): +```gherkin +Feature: Playwright site + + @slow + Scenario: Check title + Given I open url "https://playwright.dev" +``` + +## @timeout:N +Используйте тег `@timeout:N` для установки таймаута сценария: +```gherkin +Feature: Playwright site + + @timeout:5000 + Scenario: Check title + Given I open url "https://playwright.dev" +``` +Если определен на уровне фичи, он устанавливает таймаут для **каждого сценария** внутри, а не для самой фичи. См. [`test.describe.configure`](https://playwright.dev/docs/api/class-test#test-describe-configure) для деталей. Пример: +```gherkin +@timeout:5000 +Feature: Playwright site + + Scenario: Check title + Given I open url "https://playwright.dev" + + Scenario: Check navigation + Given I open url "https://playwright.dev" +``` + +## @retries:N +Используйте тег `@retries:N` для установки повторных попыток для всех сценариев в фиче: +```gherkin +@retries:2 +Feature: Playwright site + + Scenario: Check title + Given I open url "https://playwright.dev" +``` +Или установите повторные попытки для отдельного сценария: +```gherkin +Feature: Playwright site + + @retries:2 + Scenario: Check title + Given I open url "https://playwright.dev" +``` +> Когда тег `@retries` применяется к отдельному сценарию, сгенерированный тест оборачивается в *анонимный describe*, см. [microsoft/playwright#10825](https://github.com/microsoft/playwright/issues/10825) + +## @mode:xxx +Используйте один из следующих тегов для установки [режима выполнения](https://playwright.dev/docs/test-parallel#parallelize-tests-in-a-single-file) для фичи или схемы сценария: + +* `@mode:parallel` +* `@mode:serial` +* `@mode:default` + +Пример: + +```gherkin +@mode:parallel +Feature: Playwright site + + Scenario: Scenario 1 + Given I open url "https://playwright.dev" + + Scenario: Scenario 2 + Given I open url "https://playwright.dev" +``` + +Оба `Scenario 1` и `Scenario 2` будут выполнены параллельно в отдельных воркерах. + +При использовании `@mode:serial` вы можете ознакомиться с [Передачей данных между сценариями](ru/writing-steps/passing-data-between-scenarios.md). + +!> Обратите внимание, что тег `@mode` не применим к отдельному сценарию diff --git a/docs/ru/writing-features/tags-from-path.md b/docs/ru/writing-features/tags-from-path.md new file mode 100644 index 00000000..51a2d482 --- /dev/null +++ b/docs/ru/writing-features/tags-from-path.md @@ -0,0 +1,49 @@ +# Теги из пути + +Теги из пути это мощный способ автоматически назначать теги фичам через **директории или имена файлов с префиксом `@`**. Это позволяет связывать фичи с определениями шагов и сокращает явное тегирование. + +Пример: +``` +features +├── @game <- устанавливает тег @game для всех файлов внутри +│ ├── game.feature +│ └── steps.ts +└── @video-player <- устанавливает тег @video-player для всех файлов внутри + ├── video-player.feature + └── steps.ts +``` + +Путь `features/@game/game.feature` автоматически назначает тег `@game` фиче. Это эквивалентно: +```gherkin +@game +Feature: Game + + ... +``` + +Это работает и с именами файлов: +``` +features +├── @game.feature +├── @video-player.feature +└── ... +``` + +Определения шагов внутри `@`-директорий также [автоматически тегируются и ограничиваются](ru/writing-steps/scoped.md#tags-from-path) связанными фичами. Все определения из `@game/steps.ts` ограничены `@game/game.feature`. + +Эта техника открывает новые возможности для организации и изоляции тестов. + +Более того, вы можете использовать [специальные теги](ru/writing-features/special-tags.md) в качестве имен директорий: + +``` +features +└── @game + ├── @slow <- для фич, которым нужно больше времени + │ └── feature1.feature + ├── @skip <- для фич, которые не готовы + │ └── feature2.feature + ├── @mode:serial <- для фич, запускаемых в последовательном режиме + │ └── feature3.feature + ├── game.feature + └── steps.ts +``` diff --git a/docs/ru/writing-steps/bdd-fixtures.md b/docs/ru/writing-steps/bdd-fixtures.md new file mode 100644 index 00000000..1d7d2dbe --- /dev/null +++ b/docs/ru/writing-steps/bdd-fixtures.md @@ -0,0 +1,131 @@ +# Фикстуры Playwright-BDD +Playwright-BDD предоставляет встроенные фикстуры для удобной разработки. + +?> Все BDD фикстуры имеют префикс `$`, чтобы избежать коллизии имен с пользовательскими фикстурами. + +> См. также [Доступ к BDD фикстурам в шагах-декораторах](ru/writing-steps/decorators.md#accessing-bdd-fixtures). + +## `$test` и `$testInfo` +Вы можете получить доступ к [`test`](https://playwright.dev/docs/api/class-test) и [`testInfo`](https://playwright.dev/docs/api/class-testinfo) в теле шага, используя специальные фикстуры `$test` и `$testInfo` соответственно. Это позволяет вам: + + * изменять таймаут теста + * условно пропускать тесты + * прикреплять скриншоты + * выполнять все другие действия через объект `testInfo` + +Пример - пропустить тест для `firefox`: +```ts +Given('I do something', async ({ browserName, $test }) => { + if (browserName === 'firefox') $test.skip(); + // ... +}); +``` + +## `$step` +Вы можете получить доступ к информации о текущем шаге, используя специальную фикстуру `$step`. +В настоящее время она содержит только заголовок шага, но может быть расширена в будущем. + +```ts +Given('I open url {string}', async ({ $step }, url: string) => { + console.log($step.title); // I open url "https://playwright.dev" + // ... +}); +``` + +#### Пример +Популярный случай использования фикстуры `$step` - это дополнительное сопоставление по заголовку шага. + +Представьте, что у вас есть универсальный шаг для проверки того, виден элемент или скрыт: +```ts +Then('element with text {string} should( not) be displayed', ...) +``` +Паттерн содержит опциональное сопоставление `should( not)`, которое [недоступно](https://github.com/cucumber/cucumber-expressions/issues/125) внутри функции шага. Самый простой способ дополнительно проверить `( not)` - использовать заголовок шага: +```ts +Then('element with text {string} should( not) be displayed', async ({ page, $step }, text: string) => { + const negate = /should not/.test($step.title); + if (negate) { + await expect(page.getByText(text)).toBeHidden(); + } else { + await expect(page.getByText(text)).toBeVisible(); + } +}); +``` + +## `$tags` +Вы можете получить доступ к текущим тегам теста, используя специальную фикстуру `$tags`: + +```gherkin +@slow +Feature: Playwright site + + @jira:123 + Scenario: Check title + Given I do something + ... +``` +В определении шага: +```ts +Given('I do something', async ({ $tags }) => { + console.log($tags); // выводит ["@slow", "@jira:123"] +}); +``` + +Наиболее мощное использование `$tags` - в ваших пользовательских фикстурах. + +##### Пример 1: Запуск теста в конкретном браузере + +Представьте, что вы хотите запустить сценарий только в Firefox, если есть тег `@firefox`: +```gherkin +Feature: some feature + + @firefox + Scenario: Runs only in Firefox + ... +``` + +Настройте пользовательскую фикстуру, которая проверяет `$tags` и пропускает тест в не-firefox браузере: +```ts +import { test as base } from 'playwright-bdd'; + +export const test = base.extend<{ firefoxOnly: void }>({ + firefoxOnly: [ + async ({ $tags, defaultBrowserType }, use, testInfo) => { + if ($tags.includes('@firefox') && defaultBrowserType !== 'firefox') { + testInfo.skip(); + } + await use(); + }, + { auto: true }, + ], +}); +``` + +##### Пример 2: Установка локали для теста +Перезапишите локаль на `fi`, если тест имеет тег `@LocaleFi`: +```ts +import { test as base } from 'playwright-bdd'; + +export const test = base.extend({ + locale: async ({ $tags, locale }, use) => { + if ($tags.includes('@LocaleFi')) { + locale = 'fi'; + } + await use(locale); + }, +}); +``` + +##### Пример 3: Переключение на мобильный viewport для теста +Перезапишите `viewport` для сценариев с тегом `@mobile`: +```ts +import { test as base } from 'playwright-bdd'; + +export const test = base.extend({ + viewport: async ({ $tags, viewport }, use) => { + if ($tags.includes('@mobile')) { + viewport = { width: 375, height: 667 }; + } + await use(viewport); + } +}); +``` diff --git a/docs/ru/writing-steps/cucumber-style.md b/docs/ru/writing-steps/cucumber-style.md new file mode 100644 index 00000000..bfe527c6 --- /dev/null +++ b/docs/ru/writing-steps/cucumber-style.md @@ -0,0 +1,119 @@ +# Шаги в стиле Cucumber + +Определения шагов в стиле Cucumber совместимы с [CucumberJS](https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/step_definitions.md). + + * определения шагов используют World (`this`) для взаимодействия с браузером + * определения шагов получают только параметры шага, не получают пользовательские фикстуры в качестве первого аргумента + * определения шагов не могут быть определены как стрелочные функции + +С точки зрения Playwright, World - это просто фикстура с областью видимости теста, которая автоматически предоставляется всем определениям шагов. + +С версии **Playwright-BDD v7** вы можете определить World как пользовательский класс, без расширения Cucumber World. Структура World зависит от вас, вы можете передать любые фикстуры как свойства world и использовать их позже в определениях шагов. + +**Пример настройки в стиле cucumber:** + +1. Определите World: + +```ts +// world.ts +import { Page } from '@playwright/test'; + +export class World { + constructor(public page: Page) {} + + async openHomePage() { + await this.page.goto('https://playwright.dev'); + } +} +``` + +> Нет необходимости вызывать `setWorldConstructor`, как это было раньше для [пользовательского world в CucumberJs](https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/world.md#custom-worlds). + +2. Расширьте тест Playwright фикстурой `world` и создайте `Given / When / Then`: + +```ts +// fixtures.ts +import { test as base } from 'playwright-bdd'; +import { World } from './world'; + +export const test = base.extend<{ world: World }>({ + world: async ({ page }, use) => { + const world = new World(page); + await use(world); + }, +}); + +export const { Given, When, Then, Before, After } = createBdd(test, { + worldFixture: 'world' +}); +``` + +> Убедитесь, что вы экспортируете экземпляр `test`, потому что он используется в сгенерированных тестовых файлах + +3. Используйте эти `Given / When / Then` для определения шагов, экземпляр world доступен как `this`: + +```ts +// steps.ts +import { Given, When, Then } from './fixtures'; + +Given('I am on home page', async function () { + await this.openHomePage(); +}); +``` + +См. [полный пример стиля Cucumber](https://github.com/vitalets/playwright-bdd/tree/main/examples/cucumber-style). + +### Пользовательские фикстуры +Вы можете предоставить пользовательские фикстуры шагам в стиле cucumber. +Чтобы достичь этого, назначьте пользовательскую фикстуру свойству объекта World +и затем обращайтесь к ней через `this`: + +```ts +// fixtures.ts +import { test as base } from 'playwright-bdd'; + +type World = { + page: Page; + myFixture: MyFixture; // <- свойство пользовательской фикстуры +}; + +export const test = base.extend<{ world: World }>({ + myFixture: async ({}, use) => { + // настройка myFixture... + }, + world: async ({ page, myFixture }, use) => { + const world: World = { page, myFixture }; + await use(world); + }, +}); + +export const { Given, When, Then, Before, After } = createBdd(test, { + worldFixture: 'world' +}); +``` + +Используйте `this.myFixture` в определениях шагов: +```ts +import { Given, When, Then } from './fixtures'; + +Given('I am on home page', async function () { + console.log(this.myFixture); +}); +``` + +### Есть ли world по умолчанию? +Нет. Вы определяете весь World с нуля. + +В простейшем случае вы можете создать world как простой объект со свойством `page`: +```js +import { test as base } from 'playwright-bdd'; + +export const test = base.extend({ + world: async ({ page }, use) => { + const world = { page }; + await use(world); + }, +}); + +export const { Given, When, Then, Before, After } = createBdd(test, { worldFixture: 'world' }); +``` diff --git a/docs/ru/writing-steps/data-tables.md b/docs/ru/writing-steps/data-tables.md new file mode 100644 index 00000000..0f03f489 --- /dev/null +++ b/docs/ru/writing-steps/data-tables.md @@ -0,0 +1,33 @@ +# Использование `DataTables` +Playwright-BDD предоставляет полную поддержку [`DataTables`](https://cucumber.io/docs/gherkin/reference/#data-tables). +Например: +```gherkin +Feature: Some feature + + Scenario: Login + When I fill login form with values + | label | value | + | Username | vitalets | + | Password | 12345 | +``` + +Определение шага: +```ts +import { createBdd, DataTable } from 'playwright-bdd'; + +const { Given, When, Then } = createBdd(); + +When('I fill login form with values', async ({ page }, data: DataTable) => { + for (const row of data.hashes()) { + await page.getByLabel(row.label).fill(row.value); + } + /* + data.hashes() возвращает: + [ + { label: 'Username', value: 'vitalets' }, + { label: 'Password', value: '12345' } + ] + */ +}); +``` +Ознакомьтесь со всеми [методами DataTable](https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/data_table_interface.md) в документации Cucumber. diff --git a/docs/ru/writing-steps/decorators.md b/docs/ru/writing-steps/decorators.md new file mode 100644 index 00000000..da924b78 --- /dev/null +++ b/docs/ru/writing-steps/decorators.md @@ -0,0 +1,154 @@ +# Декораторы +Playwright-BDD поддерживает [декораторы TypeScript v5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#decorators) как удобный способ определения шагов прямо внутри [Page Object Models (POM)](https://playwright.dev/docs/pom). + +Декораторы импортируются из `playwright-bdd/decorators`: +```ts +import { Fixture, Given, When, Then } from 'playwright-bdd/decorators'; +``` + +Примените декоратор `@Fixture` ко всему классу, чтобы связать его с именем фикстуры Playwright. Примените декораторы `@Given, @When, @Then` к конкретным методам: +```ts +// TodoPage.ts +import { Page, expect } from '@playwright/test'; +import { Fixture, Given, When, Then } from 'playwright-bdd/decorators'; + +export @Fixture('todoPage') class TodoPage { + constructor(public page: Page) { } + + @Given('I am on todo page') + async open() { + await this.page.goto('https://demo.playwright.dev/todomvc/'); + } + + @When('I add todo {string}') + async addToDo(text: string) { + await this.page.locator('input.new-todo').fill(text); + await this.page.locator('input.new-todo').press('Enter'); + } + + @Then('visible todos count is {int}') + async checkVisibleTodosCount(count: number) { + await expect(this.page.getByTestId('todo-item')).toHaveCount(count); + } +} +``` + +Затем используйте этот класс в `test.extend` как обычную фикстуру: +```ts +// fixtures.ts +import { test as base } from 'playwright-bdd'; +import { TodoPage } from './TodoPage'; + +export const test = base.extend<{ todoPage: TodoPage }>({ + todoPage: ({ page }, use) => use(new TodoPage(page)), +}); +``` + +И добавьте `fixtures.ts` к шагам в `playwright.config.ts`: +```ts +const testDir = defineBddConfig({ + features: 'features/todo.feature', + steps: 'fixtures.ts', + // ... +}); +``` + +Теперь вы можете использовать эти шаги в файлах `.feature`: +```gherkin +# features/todo.feature +Feature: Todo Page + + Scenario: Adding todos + Given I am on todo page + When I add todo "foo" + And I add todo "bar" + Then visible todos count is 2 +``` +Ознакомьтесь с [полным примером использования декораторов](https://github.com/vitalets/playwright-bdd/tree/main/examples/decorators) с playwright-bdd. + +> Чтобы автодополнение VSCode Cucumber работало с декораторами, установите `cucumberautocomplete.strictGherkinCompletion = false` в `.vscode/settings.json` + +## Наследование +Когда один Page Object наследуется от другого, `playwright-bdd` может автоматически угадать, +какую фикстуру использовать в конкретном сценарии. Представьте два класса родитель-потомок с шагами-декораторами: + +```ts +// TodoPage +export @Fixture('todoPage') class TodoPage { + @Given('I am on todo page') + async open() { ... } +} + +// AdminTodoPage унаследованный от TodoPage +export @Fixture('adminTodoPage') class AdminTodoPage extends TodoPage { + @When('I add todo {string}') + async addToDo(text: string) { ... } +} +``` + +И сценарий, который использует оба шага: + +```gherkin +Scenario: Adding todos + Given I am on todo page # <- шаг определен в TodoPage + When I add todo "foo" # <- шаг определен в AdminTodoPage +``` + +Здесь Playwright-BDD будет использовать единую фикстуру `AdminTodoPage` для обоих шагов вместо создания двух отдельных фикстур. + +?> Убедитесь, что и родительские, и дочерние POM покрыты паттерном `steps` в конфигурации. + +В некоторых случаях вы можете захотеть принудительно использовать конкретную фикстуру. +Для этого вы можете применить специальный тег `@fixture:%name%`: + +```gherkin +@fixture:adminTodoPage +Feature: Some feature + + Background: + Given I am on todo page # <- будет использовать AdminTodoPage + + Scenario: Adding todos + When I add todo "foo" # <- будет использовать AdminTodoPage +``` + +## Доступ к BDD фикстурам + +Шаги-декораторы принимают только параметры шага. Для доступа к любым пользовательским или BDD фикстурам вы должны вручную передать требуемые фикстуры в конструктор POM и обращаться к ним через ключевое слово `this`. + +**Пример** + +1. Определите фикстуры `$tags` и `$test` как аргументы конструктора и используйте их в шаге: + +```ts +// TodoPage.ts +import { Page, expect } from '@playwright/test'; +import { Fixture, Given, When, Then } from 'playwright-bdd/decorators'; +import { test } from './fixtures'; + +export @Fixture('todoPage') class TodoPage { + constructor( + public page: Page, + protected $tags: string[], + protected $test: typeof test + ) {} + + @Given('I am on todo page') + async open() { + if (this.$tags.includes('firefox')) { + this.$test.skip(); + } + } +``` + +2. Передайте `$tags` и `$test` в конструктор POM: + +```ts +// fixtures.ts +export const test = base.extend<{ todoPage: TodoPage }>({ + todoPage: ({ page, $tags, $test }, use) => { + const todoPage = new TodoPage(page, $tags, $test as typeof test); + await use(todoPage); + }, +}); +``` diff --git a/docs/ru/writing-steps/hooks.md b/docs/ru/writing-steps/hooks.md new file mode 100644 index 00000000..da8e5ab4 --- /dev/null +++ b/docs/ru/writing-steps/hooks.md @@ -0,0 +1,469 @@ +# Хуки + +Хуки - это функции, которые автоматически запускаются до/после воркеров или сценариев: + +* `BeforeWorker / BeforeAll` - запускается **один раз в каждом воркере**, перед всеми сценариями +* `AfterWorker / AfterAll` - запускается **один раз в каждом воркере**, после всех сценариев +* `BeforeScenario / Before` - запускается **перед каждым сценарием** +* `AfterScenario / After` - запускается **после каждого сценария** +* `BeforeStep` - запускается **перед каждым шагом** +* `AfterStep` - запускается **после каждого шага** + +> Если вам нужно запустить код **до/после общего выполнения тестов**, ознакомьтесь с [зависимостями проектов](https://playwright.dev/docs/test-global-setup-teardown#option-1-project-dependencies) или [глобальной настройкой и завершением](https://playwright.dev/docs/test-global-setup-teardown#option-2-configure-globalsetup-and-globalteardown) Playwright + +## Фикстуры + +Хотя хуки являются хорошо известной концепцией, Playwright предлагает лучшую альтернативу - [фикстуры](https://playwright.dev/docs/test-fixtures#introduction). В большинстве случаев фикстуры могут полностью заменить хуки и предоставить [много преимуществ](https://playwright.dev/docs/test-fixtures#with-fixtures). По умолчанию всегда рассматривайте использование фикстур. + +#### Пример переписывания кода с хуков на фикстуры + +Представьте сценарий с шагом, требующим авторизации пользователя: +```gherkin +Feature: Some feature + + Scenario: Some scenario + Given I am an authorized user +``` +Нам нужно обернуть сценарий действиями входа/выхода. + +**В Cucumber** вы можете добавить тег (например, `@auth`) к этому сценарию: +```gherkin +Feature: Some feature + + @auth + Scenario: Some scenario + Given I am an authorized user +``` +И зарегистрировать хуки `Before / After` для запуска с этим тегом: + +```ts +Before({ tags: '@auth' }, async function () { + // выполнить вход +}); + +After({ tags: '@auth' }, async function () { + // выполнить выход +}); +``` + +**В Playwright** вы можете создать следующую фикстуру `auth`: +```ts +export const test = base.extend({ + auth: async ({}, use) => { + // выполнить вход + await use({ username: 'some user' }); + // выполнить выход + } +}); +``` +и использовать эту фикстуру `auth` в шаге: +```ts +Given('I am an authorized user', async ({ auth }) => { + console.log('step for authorized user', auth.username); +}); +``` +Playwright автоматически обернет код теста входом и выходом пользователя. + +Преимущества использования фикстур: +- фикстура выполняется только когда фактически используется +- нет дополнительных тегов +- код фикстуры переиспользуется в других фичах + +## BeforeWorker / BeforeAll + +> Рассмотрите использование [фикстур](#fixtures) вместо хуков. + +Playwright-BDD поддерживает хук уровня воркера `BeforeWorker` (с псевдонимом `BeforeAll`). Он запускается **один раз в каждом воркере, перед всеми сценариями**. + +?> Хотя `BeforeAll` более используемое имя, `BeforeWorker` лучше выражает, когда запускается хук. + +#### Использование + +1. Создайте и экспортируйте функцию `BeforeWorker`: + + ```ts + // fixtures.ts + import { test as base, createBdd } from 'playwright-bdd'; + + export const test = base.extend({ /* ...ваши фикстуры */ }); + + export const { BeforeWorker } = createBdd(test); + ``` + +2. Определите хуки: + + ```ts + // hooks.ts + import { BeforeWorker } from './fixtures'; + + BeforeWorker(async ({ $workerInfo, browser }) => { + // ...этот код запускается один раз в каждом воркере и использует фикстуры с областью видимости воркера + }); + ``` + +С версии Playwright-BDD **v8** вы можете привязать хук воркера к конкретным фичам через `tags`: + +```ts +BeforeWorker({ tags: '@auth' }, async () => { ... }); +``` + +Это эффективно работает как хук **BeforeFeature**. + +Вы также можете предоставить теги по умолчанию через `createBdd()`: +```ts +const { BeforeWorker } = createBdd(test, { tags: '@mobile' }); + +BeforeWorker(async () => { + // запускается только для фич с @mobile +}); +``` + +Дополнительно вы можете установить `name` и `timeout` для хука: +```ts +BeforeWorker({ name: 'setup database', timeout: 1000 }, async () => { + // запускается с таймаутом 1000 мс +}); +``` + +Функция хука принимает **1 аргумент** - [фикстуры с областью видимости воркера](https://playwright.dev/docs/test-fixtures#worker-scoped-fixtures). +Вы можете получить доступ к [$workerInfo](https://playwright.dev/docs/api/class-workerinfo) и любым встроенным или пользовательским фикстурам. См. подробности в [BeforeWorker / BeforeAll API](api.md#beforeworker-beforeall). + +#### Пример использования `BeforeWorker` с пользовательской фикстурой + +Представьте, что вы определили пользовательскую фикстуру воркера `myWorkerFixture`: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend<{}, { myWorkerFixture: MyWorkerFixture }>({ + myWorkerFixture: [async ({}, use) => { + // ... настройка myWorkerFixture + }, { scope: 'worker' }] +}); + +export const { BeforeWorker } = createBdd(test); +``` + +Теперь вы можете использовать `myWorkerFixture` в созданных хуках: +```ts +import { BeforeWorker } from './fixtures'; + +BeforeWorker(async ({ myWorkerFixture }) => { + // ... использование myWorkerFixture в хуке +}); +``` + +> Обратите внимание, что в хуках `BeforeWorker / AfterWorker` **нет доступа к World**, потому что World пересоздается для каждого теста. Вот [обсуждение](https://github.com/cucumber/cucumber-js/issues/1393) в репозитории Cucumber. + +?> Если вам нужно запустить хук **один раз для всех воркеров**, ознакомьтесь с [Запуск хука один раз](#running-hook-once). + +## AfterWorker / AfterAll + +> Рассмотрите использование [фикстур](#fixtures) вместо хуков. + +Playwright-BDD поддерживает хук уровня воркера `AfterWorker` (с псевдонимом `AfterAll`). +Он запускается **один раз в каждом воркере, после всех сценариев**. + +?> Хотя `AfterAll` более используемое имя, `AfterWorker` лучше выражает, когда запускается хук. + +Использование: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend({ /* ...ваши фикстуры */ }); + +const { AfterWorker } = createBdd(test); + +AfterWorker(async ({ $workerInfo, browser }) => { + // запускается когда каждый воркер завершается +}); +``` + +Все опции и поведение аналогичны [BeforeWorker / BeforeAll](#beforeworker-beforeall). + +## BeforeScenario / Before + +> Рассмотрите использование [фикстур](#fixtures) вместо хуков. + +Playwright-BDD поддерживает хук уровня сценария `BeforeScenario` (с псевдонимом `Before`). Он запускается **перед каждым сценарием**. + +?> Хотя `Before` более используемое имя, `BeforeScenario` лучше выражает, когда запускается хук. + + + +#### Использование + +1. Создайте и экспортируйте функцию `BeforeScenario`: + + ```ts + // fixtures.ts + import { test as base, createBdd } from 'playwright-bdd'; + + export const test = base.extend({ /* ...ваши фикстуры */ }); + + export const { BeforeScenario } = createBdd(test); + ``` + +2. Определите хуки сценария: + + ```ts + // hooks.ts + import { BeforeScenario } from './fixtures'; + + BeforeScenario(async () => { + // запускается перед каждым сценарием + }); + ``` + +С версии Playwright-BDD **v8** вы можете нацелить хук сценария на конкретные фичи/сценарии через `tags`: + +```ts +BeforeScenario({ tags: '@mobile and not @slow' }, async () => { + // запускается перед сценариями с тегами @mobile и не @slow +}); +``` + +Если вы хотите передать только теги, можете использовать сокращение: +```ts +BeforeScenario('@mobile and not @slow', async () => { + // запускается для сценариев с @mobile и не @slow +}); +``` + +Вы также можете предоставить теги по умолчанию через `createBdd()`: +```ts +const { BeforeScenario } = createBdd(test, { tags: '@mobile' }); + +BeforeScenario(async () => { + // запускается только для сценариев с @mobile +}); +``` + +Если хук имеет и теги по умолчанию, и собственные теги, они объединяются с использованием логики `AND`: +```ts +const { BeforeScenario } = createBdd(test, { tags: '@mobile' }); + +BeforeScenario({ tags: '@slow' }, async function () { + // запускается для сценариев с @mobile и @slow +}); +``` + +Дополнительно вы можете установить `name` и `timeout` для хука: +```ts +BeforeScenario({ name: 'my hook', timeout: 5000 }, async function () { + // ... +}); +``` + +Функция хука принимает **1 аргумент** - [фикстуры с областью видимости теста](https://playwright.dev/docs/test-fixtures#built-in-fixtures). Вы можете получить доступ к [$testInfo](https://playwright.dev/docs/api/class-testinfo), [$tags](writing-steps/bdd-fixtures.md#tags) и любым встроенным или пользовательским фикстурам. См. подробности в [BeforeScenario / Before API](api.md#beforescenario-before). + +#### Пример использования `BeforeScenario` с пользовательской фикстурой + +Представьте, что вы определили пользовательскую фикстуру `myFixture`: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend<{ myFixture: MyFixture }>({ + myFixture: async ({ page }, use) => { // <-- пользовательская фикстура + // ... + } +}); + +export const { BeforeScenario } = createBdd(test); +``` + +Теперь вы можете использовать `myFixture` в созданных хуках: +```ts +import { BeforeScenario } from './fixtures'; + +BeforeScenario(async ({ myFixture }) => { + // ... использование myFixture в хуке +}); +``` + +## AfterScenario / After + +> Рассмотрите использование [фикстур](#fixtures) вместо хуков. + +Playwright-BDD поддерживает хук уровня сценария `AfterScenario` (с псевдонимом `After`). Он запускается **после каждого сценария**. + +?> Хотя `After` более используемое имя, `AfterScenario` лучше выражает, когда запускается хук. + +Использование: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend({ /* ...ваши фикстуры */ }); + +const { AfterScenario } = createBdd(test); + +AfterScenario(async () => { + // запускается после каждого сценария +}); +``` + +Все опции и поведение аналогичны [BeforeScenario / Before](#beforescenario-before). + +## BeforeStep + +Playwright-BDD поддерживает хук уровня шага `BeforeStep`. Он запускается **перед каждым шагом**. + +Использование: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend({ /* ...ваши фикстуры */ }); + +const { BeforeStep } = createBdd(test); + +BeforeStep(async () => { + // запускается перед каждым шагом +}); +``` + +Вы можете нацелить хук шага на шаги конкретной фичи/сценария через `tags`: + +```ts +BeforeStep({ tags: '@mobile and not @slow' }, async function () { + // запускается для сценариев с @mobile и не @slow +}); +``` +Если вы хотите передать только теги, можете использовать сокращение: +```ts +BeforeStep('@mobile and not @slow', async function () { + // запускается для сценариев с @mobile и не @slow +}); +``` +Вы также можете предоставить теги по умолчанию через `createBdd()`: +```ts +const { BeforeStep } = createBdd(test, { tags: '@mobile' }); + +BeforeStep(async () => { + // запускается только для сценариев с @mobile +}); +``` + +Если хук имеет и теги по умолчанию, и собственные теги, они объединяются с использованием логики `AND`: +```ts +const { BeforeStep } = createBdd(test, { tags: '@mobile' }); + +BeforeStep({ tags: '@slow' }, async function () { + // запускается для сценариев с @mobile и @slow +}); +``` + +Дополнительно вы можете установить `name` и `timeout` для хука: +```ts +BeforeStep({ name: 'my hook', timeout: 5000 }, async function () { + // ... +}); +``` + +Функция хука принимает **1 аргумент** - [фикстуры с областью видимости теста](https://playwright.dev/docs/test-fixtures#built-in-fixtures). Вы можете получить доступ к [$testInfo](https://playwright.dev/docs/api/class-testinfo), [$tags](writing-steps/bdd-fixtures.md#tags) и любым встроенным или пользовательским фикстурам. См. подробности в [BeforeScenario / Before API](api.md#beforescenario-before). + +## AfterStep + +> Рассмотрите использование [фикстур](#fixtures) вместо хуков. + +Playwright-BDD поддерживает хук уровня сценария `AfterStep`. Он запускается **после каждого шага**. + +Использование: +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend({ /* ...ваши фикстуры */ }); + +const { AfterStep } = createBdd(test); + +AfterStep(async () => { + // запускается после каждого сценария +}); +``` + +Все опции и поведение аналогичны [BeforeStep](#beforestep). + +#### Пример использования `AfterStep` для захвата скриншота после каждого шага + +Создайте `fixtures.ts`: +```ts +export const { AfterStep } = createBdd(test); +``` + +Импортируйте `fixtures.ts` в определение шагов +```ts +import { AfterStep } from './fixtures'; + +AfterStep(async ({ page, $testInfo, $step }) => { + await $testInfo.attach(`screenshot after ${$step.title}`, { + contentType: 'image/png', + body: await page.screenshot() + }); +}); + +// ...остальные определения шагов +``` + +## Запуск хука один раз + +`BeforeAll` / `AfterAll` запускаются **один раз на воркер**, а не один раз для всего запуска теста. Это может быть не то, что вы хотите. Например, если вы заполняете базу данных тестовыми данными, нет необходимости перезаполнять её в каждом воркере: + +```ts +import { BeforeWorker } from './fixtures'; + +BeforeWorker(async () => { + await populateDatabase(); // <-- запускается в каждом воркере +}); +``` + +Чтобы запустить код внутри хука ровно один раз, вы можете использовать [@vitalets/global-cache](https://github.com/vitalets/global-cache). Он позволяет кешировать и переиспользовать любые сериализуемые данные во всех воркерах: + +```ts +import { BeforeWorker } from './fixtures'; +import { globalCache } from '@vitalets/global-cache'; + +BeforeWorker(async () => { + await globalCache.get('populate-db', async () => { + await populateDatabase(); // <-- запускается один раз + }); +}); +``` + +> См. [README](https://github.com/vitalets/global-cache) global-cache для инструкций по настройке. + +Вы также можете использовать этот подход в хуках `BeforeScenario` для сохранения данных и [переиспользования](writing-steps/passing-data-between-steps.md) их в шагах: + +```ts +BeforeScenario(async ({ ctx }) => { + ctx.userIds = await globalCache.get('user-ids', async () => { + const userIds = await populateDatabase(); + return userIds; + }); +}); +``` + +Вы можете использовать глобальный кеш и в фикстурах. Например, оберните код в фикстуру `storageState`, чтобы аутентифицироваться только при необходимости и кешировать на 1 час: + +```ts +// fixtures.ts +import { test as base, createBdd } from 'playwright-bdd'; +import { globalCache } from '@vitalets/global-cache'; + +export const test = base.extend({ + storageState: async ({ storageState, browser }, use, testInfo) => { + // Пропустить аутентификацию для сценариев с тегом @no-auth + if (testInfo.tags.includes('@no-auth')) return use(storageState); + + // Получить состояние аутентификации один раз и закешировать на 1 час + const authState = await globalCache.get('auth-state', { ttl: '1 hour' }, async () => { + const loginPage = await browser.newPage(); + // ...аутентификация + return loginPage.context().storageState(); + }); + + await use(authState); + }, +}); + +export const { Given, When, Then } = createBdd(test); +``` + +Это может значительно ускорить ваши тесты при полностью параллельном и sharded запуске. diff --git a/docs/ru/writing-steps/index.md b/docs/ru/writing-steps/index.md new file mode 100644 index 00000000..ad4439f5 --- /dev/null +++ b/docs/ru/writing-steps/index.md @@ -0,0 +1,39 @@ +# Написание шагов + +*Определения шагов* содержат код реализации шагов сценария. +Обычно они определяются с помощью функций `Given()`, `When()`, `Then()`. +Существует 3 способа написания шагов в Playwright-BDD: + +1. [Стиль Playwright](ru/writing-steps/playwright-style.md) - пишите шаги так же, как пишете тесты Playwright, рекомендуется для новых BDD проектов или существующих проектов Playwright. +2. [Стиль Cucumber](ru/writing-steps/cucumber-style.md) - пишите шаги совместимым с CucumberJS способом, используйте `this` для доступа к world и фикстурам Playwright. Рекомендуется для миграции проектов CucumberJS на раннер Playwright. +3. [Декораторы](ru/writing-steps/decorators.md) - помечайте методы классов POM как шаги, рекомендуется для всех проектов. + +#### Базовые примеры стилей шагов + +Шаг в стиле Playwright: +```ts +Given('I open page {string}', async ({ page }, url: string) => { + await page.goto(url); +}); +``` + +Шаг в стиле Cucumber: +```ts +Given('I open page {string}', async function (url: string) => { + await this.page.goto(url); +}); +``` + +Декораторы: +```ts +class TodoPage { + @Given('I open page {string}') + async open(url: string) { + await this.page.goto(url); + } +} +``` + +Ознакомьтесь с соответствующими разделами, чтобы узнать больше о каждом стиле. + +?> Обратите внимание, что нет функций `And()` / `But()`, так как эти ключевые слова используются только для лучшей семантики в файлах `.feature`. diff --git a/docs/ru/writing-steps/keywords-matching.md b/docs/ru/writing-steps/keywords-matching.md new file mode 100644 index 00000000..7ee9022d --- /dev/null +++ b/docs/ru/writing-steps/keywords-matching.md @@ -0,0 +1,48 @@ +# Сопоставление ключевых слов + +По умолчанию ключевое слово определения шага (например, `Given` против `When` против `Then`) [не учитывается](https://cucumber.io/docs/gherkin/reference/#steps) при сопоставлении с шагами сценария. + +Например, следующее определение с `Given`: +```js +Given('a step', () => { ... }); +``` +успешно соответствует любому из этих шагов: +```gherkin +Given a step +When a step +Then a step +``` + +В некоторых случаях вы можете захотеть ограничить такое поведение и требовать сопоставления ключевых слов в дополнение к паттерну шага. С версии **Playwright-BDD v8** вы можете включить это с помощью опции [`matchKeywords`](ru/configuration/options.md#matchkeywords): + +```js +// playwright.config.js +import { defineConfig } from '@playwright/test'; +import { defineBddConfig } from 'playwright-bdd'; + +const testDir = defineBddConfig({ + matchKeywords: true, + // ... +}); + +export default defineConfig({ + testDir, +}); +``` + +Теперь, если вы запустите код из предыдущего примера, вы получите ошибку отсутствующего определения шага: +``` +Missing step definitions: 1 + +When('a step', async ({}) => { + // Step: When a step + // From: features/homepage.feature:4:5 +}); + +Use snippets above to create missing steps. +``` + +#### Правила `matchKeywords: true` +1. Если шаг сценария начинается с `Given`, `When`, `Then` → он соответствует только определениям с соответствующим ключевым словом или универсальной функцией `Step`. +2. Если шаг сценария начинается с `And` / `But` → он ищет ближайшее полное ключевое слово (`Given, When, Then`) и следует правилу 1. Если это первый шаг сценария, он трактуется как `Given`. +3. Если шаг сценария начинается с `*` → он соответствует любому ключевому слову. diff --git a/docs/ru/writing-steps/passing-data-between-scenarios.md b/docs/ru/writing-steps/passing-data-between-scenarios.md new file mode 100644 index 00000000..86f90d87 --- /dev/null +++ b/docs/ru/writing-steps/passing-data-between-scenarios.md @@ -0,0 +1,76 @@ +# Передача данных между сценариями + +!> Обратите внимание, что последовательный режим **не рекомендуется** командой Playwright + +При использовании [последовательного режима](https://playwright.dev/docs/test-parallel#serial-mode) Playwright вам может понадобиться передавать данные между сценариями внутри файла фичи. + +Подход аналогичен [передаче данных между шагами](ru/writing-steps/passing-data-between-steps.md). +Вы создаете контекстную переменную, записываете в неё в одном сценарии и читаете в другом. +Единственное отличие в том, что контекстная переменная существует в глобальной области видимости и хранит отображение контекста на файл фичи. + +Рассмотрим пример - совместное использование одного и того же экземпляра `page` между сценариями в файле. Вы можете залогинить пользователя в первом сценарии, а затем выполнить все проверки в последующих сценариях: + +```gherkin +@mode:serial +Feature: My feature + + Scenario: Authenticate + Given I am logged in as "user1" + + Scenario: Check profile + # все еще на той же странице с тем же контекстом! + When I open profile page + Then I see name "user1" +``` + +#### Реализация +Реализация использует две фикстуры: + +- `ctx` с областью видимости теста: хранит контекст для текущего файла +- `ctxMap` с областью видимости воркера: хранит карту всех контекстов и файлов в воркере + +```ts +import { test as base, createBdd } from 'playwright-bdd'; + +// контекст, разделяемый между сценариями в файле +type Ctx = { page: Page }; + +export const test = base.extend<{ ctx: Ctx }, { ctxMap: Record }>({ + ctx: async ({ ctxMap }, use, testInfo) => { + // получить или инициализировать контекст для текущего файла + ctxMap[testInfo.file] = ctxMap[testInfo.file] || {}; + // передать контекст сценариям как фикстуру `ctx` + await use(ctxMap[testInfo.file]); + }, + ctxMap: [async ({}, use) => { + const ctxMap: Record = {}; + await use(ctxMap); + // очистить все контексты при завершении воркера + for (const ctx of Object.values(ctxMap)) await ctx.page?.close(); + }, { scope: 'worker' }], +}); + +export const { Given, When, Then } = createBdd(test); +``` + +#### Использование +Теперь вы можете использовать фикстуру `ctx` в шагах, она будет сохраняться между сценариями: + +```ts +import { Given, When, Then } from "./fixtures"; + +Given("I am logged in as {string}", async ({ ctx, browser }, user: string) => { + ctx.page = await browser.newPage(); + // ...выполнить логин для пользователя +}); + +When("I open profile page", async ({ ctx }) => { + await ctx.page.getByRole("link", { name: "Profile" }).click(); +}); + +Then("I see name {string}", async ({ ctx }, user: string) => { + await expect(ctx.page.getByRole("header")).toContainText(user); +}); +``` + +Обратите внимание, что шаги не используют встроенную фикстуру `page` Playwright, так как она пересоздается для каждого сценария. diff --git a/docs/ru/writing-steps/passing-data-between-steps.md b/docs/ru/writing-steps/passing-data-between-steps.md new file mode 100644 index 00000000..0f13e5a3 --- /dev/null +++ b/docs/ru/writing-steps/passing-data-between-steps.md @@ -0,0 +1,84 @@ +# Передача данных между шагами + +При написании BDD шагов вам часто нужно передавать данные от одного шага к другому. + +Например, в одном шаге вы кликаете на ссылку, а в другом хотите проверить, что открылась новая вкладка: + +```gherkin +Feature: home page + + Scenario: check link + When I click the link + Then new tab is opened +``` + +В Cucumber `world` используется как контейнер для таких данных. World создается для каждого сценария и сохраняется между всеми шагами. Один шаг может записать данные в объект `world`, а другой может прочитать из него. + +В Playwright любая [фикстура с областью видимости теста](https://playwright.dev/docs/test-fixtures#creating-a-fixture) может использоваться как кросс-шаговый контекст. Вы можете назвать её `ctx` (для краткости) и инициализировать пустым объектом `{}`. Например: + +```js +import { test as base, createBdd } from 'playwright-bdd'; + +export const test = base.extend({ + ctx: async ({}, use) => { + const ctx = {}; + await use(ctx); + }, +}); + +export const { Given, When, Then } = createBdd(test); +``` + +Теперь вы можете использовать `ctx` в шагах для чтения и записи данных: + +```js +import { Given, When, Then } from './fixtures'; + +When('I click the link', async ({ page, ctx }) => { + ctx.newTapPromise = context.waitForEvent('page'); + await page.getByRole('link').click(); +}); + +Then('new tab is opened', async ({ ctx }) => { + const newTab = await ctx.newTapPromise; + await expect(newTab).toHaveTitle(/.*checkout/); +}); +``` + +?> Ознакомьтесь с примером [API тестирования](https://github.com/vitalets/playwright-bdd/tree/main/examples/api-testing) как демонстрацией передачи данных между шагами. + +#### Для пользователей TypeScript + +Вы можете определить тип `ctx` как `Record` или сделать его более строгим: + +```ts +type Ctx = { + newTapPromise: Promise +}; + +export const test = base.extend<{ ctx: Ctx }>({ + ctx: async ({}, use) => { + const ctx = {} as Ctx; + await use(ctx); + }, +}); + +export const { Given, When, Then } = createBdd(test); +``` + +#### Стиль Cucumber +В шагах в стиле Cucumber используйте `this` для записи и чтения данных между шагами: + +```js +import { Given, When, Then } from './fixtures'; + +When('I click the link', async function () { + this.newTapPromise = this.context.waitForEvent('page'); + await this.page.getByRole('link').click(); +}); + +Then('new tab is opened', async function () { + const newTab = await this.newTapPromise; + await expect(newTab).toHaveTitle(/.*checkout/); +}); +``` diff --git a/docs/ru/writing-steps/playwright-style.md b/docs/ru/writing-steps/playwright-style.md new file mode 100644 index 00000000..551bef38 --- /dev/null +++ b/docs/ru/writing-steps/playwright-style.md @@ -0,0 +1,103 @@ +# Шаги в стиле Playwright +Стиль Playwright позволяет писать определения шагов как обычные тесты Playwright. + +* Функции шагов принимают пользовательские фикстуры в качестве первого аргумента, остальные - это параметры шага. +* Функции шагов не используют `this` (World). +* Функции шагов можно (и нужно) определять как стрелочные функции. + +Чтобы получить `Given / When / Then` для стиля Playwright с фикстурами по умолчанию, вызовите `createBdd()` без аргументов: + +```ts +import { createBdd } from 'playwright-bdd'; + +const { Given, When, Then } = createBdd(); + +Given('I open url {string}', async ({ page }, url: string) => { + await page.goto(url); +}); + +When('I click link {string}', async ({ page }, name: string) => { + await page.getByRole('link', { name }).click(); +}); +``` + +> Обычно функции шагов асинхронные, но они также могут быть синхронными. + +См. [полный пример стиля Playwright](https://github.com/vitalets/playwright-bdd/tree/main/examples/basic-cjs). + +## Пользовательские фикстуры +Вы можете использовать [пользовательские фикстуры](https://playwright.dev/docs/test-fixtures#with-fixtures) в определениях шагов. + +1. Расширьте базовый `test` из `playwright-bdd` пользовательскими фикстурами: + ```ts + // fixtures.ts + // Примечание: импортируйте base из playwright-bdd, а не из @playwright/test! + import { test as base } from 'playwright-bdd'; + + export const test = base.extend<{ myFixture: MyFixture }>({ + myFixture: async ({ page }, use) => { + await use(new MyFixture(page)); + } + }); + ``` + > Убедитесь, что вы **экспортируете** экземпляр `test`, потому что он используется в сгенерированных файлах. + +2. Из того же файла экспортируйте `Given / When / Then`, привязанные к пользовательскому `test`: + ```ts + // fixtures.ts + // Примечание: импортируйте base из playwright-bdd, а не из @playwright/test! + import { test as base } from 'playwright-bdd'; + + export const test = base.extend<{ myFixture: MyFixture }>({ + myFixture: async ({ page }, use) => { + await use(new MyFixture(page)); + } + }); + + export const { Given, When, Then } = createBdd(test); // <- экспортируйте Given, When, Then + ``` + +3. Используйте эти `Given / When / Then` для определения шагов: + ```ts + // steps.ts + import { createBdd } from 'playwright-bdd'; + import { Given, When, Then } from './fixtures'; + + Given('I open url {string}', async ({ myFixture }, url: string) => { + // ... + }); + ``` + +!> Для пользователей TypeScript: если вы перезаписываете **только встроенные** фикстуры Playwright, вы должны передать `object` в качестве параметра generic типа в `test.extend()` для правильной типизации. + +Например, если вы перезаписываете только встроенную фикстуру `page`: +```ts +// неверно: +// export const test = base.extend({ ... }); + +export const test = base.extend({ // <- обратите внимание на параметр + page: async ({ baseURL, page }, use) => { + await page.goto(baseURL); + await use(page); + }, +}); +``` + +## World по умолчанию + +Хотя использование `this` (World) в шагах стиля Playwright не рекомендуется, некоторые пользователи все же хотят это +для плавной миграции с CucumberJS. +По этой причине Playwright-BDD предоставляет world по умолчанию как пустой объект `{}` для шагов стиля Playwright. +Вы можете использовать обычные функции (не стрелочные!) и получать доступ к world по умолчанию через `this`: + +```ts +Given('step 1', async function ({ page }) { + this.foo = 'bar'; +}); + +Then('step 2', async function () { + expect(this.foo).toEqual('bar'); +}); +``` + +> См. также [Передача данных между шагами](ru/writing-steps/passing-data-between-steps.md). diff --git a/docs/ru/writing-steps/reusing-step-fn.md b/docs/ru/writing-steps/reusing-step-fn.md new file mode 100644 index 00000000..1a907ac4 --- /dev/null +++ b/docs/ru/writing-steps/reusing-step-fn.md @@ -0,0 +1,36 @@ +# Переиспользование функции шага + +Можно переиспользовать функцию шага в других шагах для совместного использования общей функциональности. Сохраните возвращаемое значение `Given() / When() / Then()` и вызовите его в других шагах. Обратите внимание, что вы должны передать все требуемые фикстуры в первом аргументе. + +Пример: +```ts +import { createBdd } from 'playwright-bdd'; + +const { When, Then } = createBdd(); + +const createTodo = When('I create todo {string}', async ({ page }, text: string) => { + await page.getByLabel('title').fill(text); + await page.getByRole('button').click(); +}); + +When('I create 2 todos {string} and {string}', async ({ page }, text1: string, text2: string) => { + await createTodo({ page }, text1); + await createTodo({ page }, text2); +}); +``` + +#### Передача World + +Для **шагов в стиле cucumber** вы должны вызвать функцию шага через `.call()`, чтобы передать фактический World: + +```js +const createTodo = When('I create todo {string}', async function (text: string) { + await this.page.getByLabel('title').fill(text); + await this.page.getByRole('button').click(); +}); + +When('I create 2 todos {string} and {string}', async function (text1: string, text2: string) { + await createTodo.call(this, text1); + await createTodo.call(this, text2); +}); +``` diff --git a/docs/ru/writing-steps/scoped.md b/docs/ru/writing-steps/scoped.md new file mode 100644 index 00000000..8fdc0f59 --- /dev/null +++ b/docs/ru/writing-steps/scoped.md @@ -0,0 +1,149 @@ +# Ограниченные по области видимости определения шагов + +По умолчанию определения шагов глобальные и [не привязаны к конкретной фиче](https://cucumber.io/docs/guides/anti-patterns/#feature-coupled-step-definitions). Хотя это следует дизайну Cucumber, в больших проектах может быть сложно сохранять уникальность шагов для всех возможных доменов. + +Playwright-BDD предоставляет способ ограничить определения шагов конкретной фичей или сценарием. Вы можете передать выражение `tags`, сужающее область видимости определения: + +```js +Given('a step', { tags: '@foo' }, async () => { + // ... +}); +``` + +Это определение `a step` будет использоваться только для фич/сценариев с тегом `@foo`. Это позволяет иметь несколько определений одного и того же шага в проекте. + +#### Пример +Представьте, что есть две фичи *game* и *video-player*, обе имеющие шаг `I click the PLAY button`: +```gherkin +Feature: Game + + Scenario: Start playing + ... + When I click the PLAY button +``` +```gherkin +Feature: Video player + + Scenario: Start playing + ... + When I click the PLAY button +``` + +Реализация шага разная для каждой фичи: +```js +// game.steps.js +When('I click the PLAY button', async () => { + // действия для game.feature +}); +``` +```js +// video-player.steps.js +When('I click the PLAY button', async () => { + // действия для video-player.feature +}); +``` +Если вы запустите пример как есть, вы получите ошибку: +``` +Error: Multiple definitions matched scenario step! +Step: When I click the PLAY button # game.feature:6:5 + - When 'I click the PLAY button' # game.steps.js:5 + - When 'I click the PLAY button' # video-player.steps.js:5 +``` +Чтобы решить проблему, вы можете ограничить определение шага соответствующей фичей через `tags`: +```js +// game.steps.js +When('I click the PLAY button', { tags: '@game' }, async () => { + // действия для game.feature +}); +``` +```js +// video-player.steps.js +When('I click the PLAY button', { tags: '@video-player' }, async () => { + // действия для video-player.feature +}); +``` +И установить эти теги в файлах фич: +```gherkin +@game +Feature: Game + + Scenario: Start playing + ... + When I click the PLAY button +``` +```gherkin +@video-player +Feature: Video player + + Scenario: Start playing + ... + When I click the PLAY button +``` +Теперь код работает. Каждая фича использует соответствующее определение шага без конфликтов. + +## Теги по умолчанию +Вы можете предоставить теги по умолчанию для определений шагов и хуков через опции `createBdd()`: + +```ts +// game.steps.ts +const { Given, When, Then } = createBdd(test, { tags: '@game' }); + +When('I click the PLAY button', async () => { + // действия для game.feature +}); +``` + +```ts +// video-player.steps.ts +const { Given, When, Then } = createBdd(test, { tags: '@video-player' }); + +When('I click the PLAY button', async () => { + // действия для video-player.feature +}); +``` + +## Теги из пути +Вы можете предоставить теги по умолчанию для определений шагов и хуков через **директории или имена файлов с префиксом `@`**. Это удобный способ связать ваши шаги и фичи. + +Пример: +``` +features +├── @game +│ ├── game.feature +│ └── steps.ts +└── @video-player + ├── video-player.feature + └── steps.ts +``` +Это эквивалентно явному определению тега `@game` в `game.feature` и во всех определениях шагов внутри `@game/steps.ts`. С тегированной директорией вы можете опустить теги из кода - определения шагов будут ограничены автоматически: +```ts +// @game/steps.ts + +When('I click the PLAY button', /* { tags: '@game' }, */ async () => { + // ... +}); +``` + +Вы также можете добавить общие шаги для использования в обеих фичах: + +``` +features +├── @game +│ ├── game.feature +│ └── steps.ts +├── @video-player +│ ├── video-player.feature +│ └── steps.ts +└── shared-steps.ts +``` + +Вы можете использовать `@`-тегированные имена файлов также. Это позволяет хранить фичи и шаги отдельно: + +``` +features +├── @game.feature +└── @video-player.feature +steps +├── @game.ts +└── @video-player.ts +``` diff --git a/docs/ru/writing-steps/snippets.md b/docs/ru/writing-steps/snippets.md new file mode 100644 index 00000000..9218197b --- /dev/null +++ b/docs/ru/writing-steps/snippets.md @@ -0,0 +1,42 @@ +# Сниппеты + +Сниппеты позволяют быстро создать определения для отсутствующих шагов. + +Пример: + +Представьте, что вы добавили новый файл фичи: +```gherkin +Feature: Playwright site + + Scenario: Check title + Given I open url "https://playwright.dev" + When I click link "Get started" + Then I see in title "Playwright" +``` +И выполнили его без определения реализации шагов: +``` +npx bddgen && npx playwright test +``` +Вывод показывает ошибку и предоставляет сниппеты кода, которые вы можете скопировать и вставить в свою кодовую базу: +``` +Missing step definitions: 3 + +Given('I open url {string}', async ({}, arg) => { + // Step: Given I open url "https://playwright.dev" + // From: features/homepage.feature:4:5 +}); + +When('I click link {string}', async ({}, arg) => { + // Step: When I click link "Get started" + // From: features/homepage.feature:5:5 +}); + +Then('I see in title {string}', async ({}, arg) => { + // Step: Then I see in title "Playwright" + // From: features/homepage.feature:6:5 +}); + +Use the snippets above to create missing steps. +``` + +> В некоторых проектах фичи пишутся заранее, а определения шагов приходят позже. Для таких случаев вам может потребоваться разрешить генерацию тестовых файлов с отсутствующими шагами и отображать их как падающие (или fixme) сценарии. Ознакомьтесь с опцией [`missingSteps`](ru/configuration/options.md#missingsteps) для настройки этого поведения. diff --git a/scripts/validate-docs.ts b/scripts/validate-docs.ts index d083b3ef..78b2295a 100644 --- a/scripts/validate-docs.ts +++ b/scripts/validate-docs.ts @@ -45,10 +45,14 @@ function fillFileInfo(relPath: string) { marked.parse(fileInfo.content, { walkTokens: (token) => { if (token.type === 'heading') { - const anchor = slugify(token.text, { + const m = /