Прежде чем писать сквозные сценарии, нужно решить, как и где они гоняются. Конфигурация Playwright задаёт это раз и определяет всё дальнейшее: какие браузеры, какой адрес приложения, какие таймауты, где лежат тесты. Хорошая настройка с первого дня экономит много возни потом.

Установка и структура

Playwright ставится одной командой, которая заодно скачивает браузеры и создаёт каркас. Тесты держат отдельной папкой (tests/ или e2e/), конфиг — в корне.

e2e/
  products.spec.ts
  auth.spec.ts
playwright.config.ts

Файлы тестов именуют *.spec.ts. Раскладка — по доменам/потокам, как и структура frontend-проекта: тесты одного сценария рядом.

playwright.config

Конфиг описывает прогон. Минимально важны testDir, baseURL (чтобы в тестах писать относительные пути) и таймауты.

import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  testDir: "./e2e",
  timeout: 30_000,
  use: {
    baseURL: "http://localhost:3000",
    trace: "on-first-retry",
  },
  projects: [
    { name: "chromium", use: { ...devices["Desktop Chrome"] } },
    { name: "firefox", use: { ...devices["Desktop Firefox"] } },
  ],
});

baseURL означает, что в тесте пишут page.goto("/products"), а не полный адрес. trace: "on-first-retry" собирает трейс при первом повторе упавшего теста — бесценно для разбора.

Projects — браузеры и окружения

projects — параллельные конфигурации одного набора тестов. Чаще всего это браузеры (chromium, firefox, webkit), но тем же механизмом задают мобильные эмуляции или разные окружения. Набор гоняется в каждом project; начинать разумно с одного браузера, добавляя остальные по мере надобности.

Первый сценарий

Тест — функция test с шагами и проверками. expect на локаторе — web-first assertion с авто-ожиданием.

import { test, expect } from "@playwright/test";

test("открывает каталог", async ({ page }) => {
  await page.goto("/products");
  await expect(page.getByRole("heading", { name: "Каталог" })).toBeVisible();
});

page — встроенная фикстура: свежий изолированный контекст браузера на каждый тест. page.goto("/products") использует baseURL. Запуск — npx playwright test; отчёт и трейсы — из коробки.

Где это в UCP

Конфигурация — фундамент e2e: baseURL, браузеры, таймауты и трейсы заданы один раз и работают на весь набор. Это та же дисциплина «настройка из одного места», что ConfigModule/конфиг в backend. Когда каркас стоит, всё остальное — локаторы, структура, данные — встаёт на готовую основу, и продукт-инженер пишет сценарии, а не воюет с окружением.