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, интеграционный или юнит.