Когда тест Playwright падает, большинство разработчиков сразу листают к номеру строки в стек-трейсе и читают не ту часть. Самое полезное место в сообщении об ошибке: call log в середине. Там показано, какое условие Playwright проверял и что он наблюдал. Из него видно, был ли элемент отсутствующим, скрытым, задизейбленным или перекрытым оверлеем. В этом гайде: как читать все три части ошибки Playwright, что означают самые частые типы ошибок и четырёхшаговый процесс отладки который закрывает большинство падений.

Анатомия ошибки Playwright

Error: locator.click: Timeout 30000ms exceeded.
Call log:
  - waiting for getByRole('button', { name: 'Submit' })

    waiting for element to be visible, enabled and stable
    element is not visible - waiting...
    element is not visible - waiting...
    element is not visible - waiting...

  at Object.<anonymous> (tests/checkout.spec.ts:45:40)

Три части:

1. Тип ошибки и сообщение: locator.click: Timeout 30000ms exceeded (какое действие не выполнилось)

2. Call log: что Playwright делал и наблюдал во время ожидания

3. Стек-трейс: где в тестовом коде это случилось

Читай в таком порядке: сначала тип ошибки, потом call log, потом стек-трейс. Call log говорит больше всего.

Частые ошибки и что они означают

Timeout exceeded

Error: locator.click: Timeout 30000ms exceeded.

Playwright не смог выполнить действие за отведённый таймаут. Call log подскажет почему. Частые причины:

  • Элемента нет в DOM
  • Элемент есть, но скрыт (display: none, visibility: hidden, opacity: 0)
  • Элемент есть и видим, но задизейблен
  • Элемент перекрыт другим элементом (оверлей, модалка, тост-уведомление)
  • Навигация по странице не завершилась до следующего действия
Как исправить: читай call log. Там написано, какое условие не выполнилось (element is not visible, element is not stable, element is disabled). Это и есть реальная проблема.

Strict mode violation

Error: strict mode violation: getByRole('button', { name: 'OK' }) resolved to 2 elements

Локатор совпал с несколькими элементами. Playwright требует уникальных локаторов, если не указано иное.

Как исправить: конкретизировать. Добавь контекстный фильтр:

// Слишком широко
page.getByRole('button', { name: 'OK' })

// Конкретнее: ограничено модалкой
page.getByRole('dialog').getByRole('button', { name: 'OK' })

// Или nth если порядок стабилен
page.getByRole('button', { name: 'OK' }).first()

Locator not found

Error: locator.fill: Error: strict mode violation: getByLabel('Email') resolved to 0 elements

Ноль совпавших элементов. Либо локатор неверный, либо элемент ещё не появился, либо ты на другой странице.

Как исправить: проверь локатор. Открой тест с флагом --debug чтобы посмотреть состояние страницы:

npx playwright test --debug tests/login.spec.ts

Error: page.goto: Timeout 30000ms exceeded.
call log:
  navigating to "http://localhost:3000/login", waiting until "load"

Страница не загрузилась до конца. Возможные причины: сервер медленный или не запущен, опция waitUntil слишком строгая ('networkidle' на странице с фоновым поллингом), или какой-то ресурс (картинка, скрипт) подвешивает событие load.

Как исправить: проверь, запущен ли сервер. Попробуй waitUntil: 'domcontentloaded' если не нужно ждать все ресурсы. Открой вкладку Network в Trace Viewer чтобы найти зависший ресурс.

Expect timeout

Error: expect(locator).toHaveText() with timeout 5000ms
Received string: ""
Expected string: "Order confirmed"

Проверка не прошла за отведённый таймаут. Элемент есть, но содержит не тот текст (или ещё не загрузился).

Как исправить: контент реально грузится? Временно увеличь таймаут чтобы исключить проблему с тимингом: await expect(el).toHaveText('Order confirmed', { timeout: 15000 }). Если с большим таймаутом проходит: проблема с производительностью, а не с селектором.

Execution context destroyed

Error: Execution context was destroyed, most likely because of a navigation.

Playwright держал ссылку на элемент страницы, когда страница перешла на другой URL. Частая причина: ты сделал const text = page.getByText('foo') а потом перешёл на другую страницу до того как обратился к этому элементу.

Как исправить: вычисляй локаторы до навигации:

// Сломано: локатор вычисляется после навигации
const text = page.getByText('Confirmation');
await page.getByRole('button', { name: 'Submit' }).click(); // вызывает навигацию
await expect(text).toBeVisible(); // страница уже ушла

// Исправлено: проверяй до навигации или заново после
await page.getByRole('button', { name: 'Submit' }).click();
await expect(page).toHaveURL('/confirmation');
await expect(page.getByText('Order confirmed')).toBeVisible();

Target closed

Error: Target page, context or browser has been closed

Контекст браузера закрылся до того как тест завершился. Обычно это происходит когда тест вручную закрывает контекст в неправильном месте, когда блок beforeAll закрыл контекст, который ещё нужен afterAll или тестам, или когда тест упал и код очистки запустился пока что-то ещё работало.

Network errors

Error: net::ERR_CONNECTION_REFUSED at http://localhost:3000

Сервер не запущен. Проверь: запущен ли dev-сервер до старта тестов, правильный ли baseURL и правильный ли порт.

В CI добавь шаг запуска сервера перед Playwright или используй webServer в конфиге:

// playwright.config.ts
webServer: {
  command: 'npm run start',
  url: 'http://localhost:3000',
  reuseExistingServer: !process.env.CI,
},

Процесс отладки

Шаг 1: читай тип ошибки и call log. Call log показывает, что Playwright ждал и что наблюдал. Шаг 2: открой Trace Viewer. npx playwright show-trace test-results/.../trace.zip: снимок DOM показывает точно, что было на странице в момент падения. Шаг 3: запусти в режиме отладки (--debug) чтобы пройти тест шаг за шагом интерактивно. Шаг 4: используй page.pause() чтобы заморозить тест в конкретном месте и изучить вручную.

await page.goto('/checkout');
await page.pause(); // тест замирает здесь, открывается Inspector
await page.getByRole('button', { name: 'Pay' }).click();

Inspector открывает браузер с тулбаром Playwright: можно взаимодействовать со страницей, запускать локаторные запросы и наблюдать действия в реальном времени.

→ See also: Playwright Trace Viewer: отлаживайте упавшие тесты как профессионал | Отладка нестабильных тестов: практическое руководство | Assertions в Playwright: полное руководство