← назад к разделу

E2E-тест проверяет продукт целиком — но это не значит «гнать все запросы через настоящую сеть». Часть запросов удобно контролировать: подменять нестабильные внешние сервисы, фиксировать ответы для повторяемости, имитировать редкие ошибки. Playwright умеет всё это. Главное — понимать, где проходит граница.

Как раньше справлялись без инструментов

До появления встроенных инструментов перехвата разработчики настраивали отдельный прокси-сервер рядом с тестами или правили hosts-файл. Это работало, но добавляло сложность: нужно было поддерживать конфигурацию прокси, следить за его запуском и убирать за собой после тестов. Каждый тест, которому нужна была заглушка, тащил за собой инфраструктуру.

Playwright решил задачу иначе: перехват сети встроен прямо в API браузера.

route и fulfill

page.route перехватывает запросы по шаблону URL. route.fulfill отдаёт свой ответ вместо настоящего:

await page.route("**/api/rates", (route) =>
  route.fulfill({
    status: 200,
    json: { usd: 92.5 },
  }),
);

После этого любой запрос, совпадающий с шаблоном **/api/rates, получит фиксированный ответ — браузер даже не отправит его наружу. Тест перестаёт зависеть от того, вернёт ли внешний сервис сегодня курс 92.5 или 91.8.

route.continue позволяет пропустить запрос дальше, но с изменениями — например, подменить заголовок или тело запроса. Это полезно, когда нужно чуть скорректировать данные, не блокируя запрос полностью.

Имитация ошибок

Ещё одна возможность — сымитировать сбой на стороне сервера:

await page.route("**/api/payment", (route) =>
  route.fulfill({ status: 500, body: "Internal Server Error" }),
);

Такой ответ трудно воспроизвести на реальном backend специально для теста. С fulfill это делается в одну строку — и можно проверить, как продукт отображает сбой, показывает ли пользователю понятное сообщение, не ломается ли интерфейс.

Аналогично имитируют таймаут (route.abort("timedout")), пустой список, несуществующий ресурс — любое краевое состояние.

Что мокать, а что нет

Здесь проходит главная граница e2e.

Мокать стоит зависимости, которые мешают стабильности теста, но не относятся к сценарию:

  • Внешние сервисы — платёжный шлюз, карты, сторонний API: нестабильны, могут быть платными, требуют тестовых режимов.
  • Редкие состояния — ошибка сервера, пустой каталог, истёкший токен: на реальном backend их трудно воспроизвести по требованию.
await page.route("**/api/maps/**", (route) =>
  route.fulfill({ status: 200, json: { points: [] } }),
);

Мокать не стоит собственный backend на основном пути. Если в тесте оформления заказа замокать каталог, корзину и оплату — проверяется не то, что фронт и бэк работают вместе, а то, что фронт умеет рисовать заглушки. Это уже не e2e.

Правило простое: критический путь идёт через реальный backend — ради этого e2e и существует. Мокается только то, что по краям: внешнее, нестабильное, дорогое. Если хочется замокать свой API на главном сценарии — скорее всего, этот тест стоит опустить ниже по пирамиде.

Ожидание сетевого ответа

Даже без подмены сеть полезно наблюдать. Вместо waitForTimeout (фиксированной паузы) Playwright позволяет дождаться конкретного ответа:

const responsePromise = page.waitForResponse("**/api/order");
await page.click("[data-testid='submit']");
await responsePromise;

Тест не переходит к проверке, пока ответ не пришёл. Это убирает гонки между отправкой запроса и проверкой результата — один из главных источников нестабильных тестов. Подробнее об ожиданиях — в статье про утверждения и ожидание условий.

Коротко

  • page.route + route.fulfill — основной способ перехватить запрос и вернуть свой ответ.
  • route.continue пропускает запрос дальше, при необходимости с изменениями.
  • route.abort имитирует сетевую ошибку или таймаут.
  • Мокать стоит внешние зависимости и труднодостижимые краевые состояния.
  • Свой backend на критическом пути — не мокать: потеряется весь смысл сквозного теста.
  • waitForResponse вместо waitForTimeout убирает гонки и делает тест стабильнее.

Что почитать дальше

  • Утверждения и ожидание условий — как ждать правильно, без фиксированных пауз.
  • Борьба с flaky-тестами — что ещё делает тесты нестабильными и как это лечить.
  • Когда писать e2e — как выбрать уровень теста: e2e, интеграционный или юнит.