Mock APIs
Введение
Веб-API обычно реализуются как HTTP-эндпоинты. Playwright предоставляет API для мокирования и модификации сетевого трафика, как HTTP, так и HTTPS. Любые запросы, которые делает страница, включая XHRs и fetch запросы, могут быть отслежены, изменены и замокированы. С помощью Playwright вы также можете мокировать, используя HAR-файлы, содержащие несколько сетевых запросов, сделанных страницей.
Мокирование API-запросов
Следующий код перехватит все вызовы к */**/api/v1/fruits
и вернет вместо этого пользовательский ответ. Запросы к API не будут выполнены. Тест переходит на URL, который использует замокированный маршрут, и проверяет, что замокированные данные присутствуют на странице.
// Перехват маршрута к API фруктов
page.route("https://fruit.ceo/api/breeds/image/random", route -> {
List<Dictionary<String, Object>> data = new ArrayList<Dictionary<String, Object>>();
Hashtable<String, Object> dict = new Hashtable<String, Object>();
dict.put("name", "Strawberry");
dict.put("id", 21);
data.add(dict);
// выполнить маршрут с замокированными данными
route.fulfill(RequestOptions.create().setData(data));
});
// Перейти на страницу
page.navigate("https://demo.playwright.dev/api-mocking");
// Убедиться, что фрукт Strawberry виден
assertThat(page.getByText("Strawberry")).isVisible();
Из трассировки теста видно, что API никогда не вызывался, однако он был выполнен с замокированными данными.
Подробнее о продвинутой работе с сетью.
Изменение ответов API
Иногда необходимо выполнить запрос к API, но ответ нужно изменить для обеспечения воспроизводимого тестирования. В этом случае, вместо мокирования запроса, можно выполнить запрос и выполнить его с измененным ответом.
В примере ниже мы перехватываем вызов к API фруктов и добавляем новый фрукт под названием 'Loquat' в данные. Затем мы переходим на URL и проверяем, что эти данные там присутствуют:
page.route("*/**/api/v1/fruits", route -> {
Response response = route.fetch();
byte[] json = response.body();
JsonObject parsed = new Gson().fromJson(new String(json), JsonObject.class);
parsed.add(new JsonObject().add("name", "Loquat").add("id", 100));
// Выполнить с использованием оригинального ответа, изменяя тело ответа
// с данным JSON объектом.
route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(parsed.toString()));
});
// Перейти на страницу
page.navigate("https://demo.playwright.dev/api-mocking");
// Убедиться, что фрукт Loquat виден
assertThat(page.getByText("Loquat", new Page.GetByTextOptions().setExact(true))).isVisible();
В трассировке нашего теста видно, что API был вызван и ответ был изменен.
При проверке ответа видно, что наш новый фрукт был добавлен в список.
Подробнее о продвинутой работе с сетью.
Мокирование с HAR-файлами
HAR-файл — это HTTP Archive файл, который содержит запись всех сетевых запросов, сделанных при загрузке страницы. Он содержит информацию о заголовках запросов и ответов, куки, содержимом, времени и многом другом. Вы можете использовать HAR-файлы для мокирования сетевых запросов в ваших тестах. Вам нужно:
- Записать HAR-файл.
- Закоммитить HAR-файл вместе с тестами.
- Маршрутизировать запросы, используя сохраненные HAR-файлы в тестах.
Запись HAR-файла
Для записи HAR-файла мы используем метод Page.routeFromHAR() или BrowserContext.routeFromHAR(). Этот метод принимает путь к HAR-файлу и необязательный объект с опциями. Объект опций может содержать URL, так что только запросы с URL, соответствующим указанному шаблону, будут обслуживаться из HAR-файла. Если не указано, все запросы будут обслуживаться из HAR-файла.
Установка опции update
в true создаст или обновит HAR-файл с фактической сетевой информацией вместо обслуживания запросов из HAR-файла. Используйте это при создании теста для заполнения HAR реальными данными.
// Получить ответ из HAR-файла
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(true)
);
// Перейти на страницу
page.navigate("https://demo.playwright.dev/api-mocking");
// Убедиться, что фрукт виден
assertThat(page.getByText("Strawberry")).isVisible();
Изменение HAR-файла
После записи HAR-файла вы можете изменить его, открыв хешированный .txt файл внутри вашей папки 'hars' и отредактировав JSON. Этот файл должен быть закоммичен в вашу систему контроля версий. Каждый раз, когда вы запускаете этот тест с update: true
, он будет обновлять ваш HAR-файл с запросом от API.
[
{
"name": "Playwright",
"id": 100
},
// ... другие фрукты
]
Воспроизведение из HAR
Теперь, когда у вас есть записанный и измененный HAR-файл с замокированными данными, его можно использовать для обслуживания соответствующих ответов в тесте. Для этого просто отключите или удалите опцию update
. Это запустит тест против HAR-файла вместо обращения к API.
// Воспроизведение API-запросов из HAR.
// Либо используйте соответствующий ответ из HAR,
// либо отмените запрос, если ничего не соответствует.
page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions()
.setUrl("*/**/api/v1/fruits")
.setUpdate(false)
);
// Перейти на страницу
page.navigate("https://demo.playwright.dev/api-mocking");
// Убедиться, что фрукт Playwright виден
assertThat(page.getByText("Playwright", new Page.GetByTextOptions()
.setExact(true))).isVisible();
В трассировке нашего теста видно, что маршрут был выполнен из HAR-файла и API не был вызван.
Если мы проверим ответ, мы увидим, что наш новый фрукт был добавлен в JSON, что было сделано путем ручного обновления хешированного .txt
файла внутри папки hars
.
Воспроизведение HAR строго соответствует URL и HTTP-методу. Для POST-запросов также строго соответствуют POST-пейлоады. Если несколько записей соответствуют запросу, выбирается та, у которой больше всего совпадающих заголовков. Запись, приводящая к перенаправлению, будет автоматически следовать.
Аналогично записи, если имя HAR-файла заканчивается на .zip
, он считается архивом, содержащим HAR-файл вместе с сетевыми пейлоадами, хранящимися как отдельные записи. Вы также можете извлечь этот архив, отредактировать пейлоады или HAR-лог вручную и указать на извлеченный HAR-файл. Все пейлоады будут разрешены относительно извлеченного HAR-файла в файловой системе.
Запись HAR с помощью CLI
Мы рекомендуем использовать опцию update
для записи HAR-файла для вашего теста. Однако вы также можете записать HAR с помощью Playwright CLI.
Откройте браузер с помощью Playwright CLI и передайте опцию --save-har
, чтобы создать HAR-файл. При необходимости используйте --save-har-glob
, чтобы сохранять только интересующие вас запросы, например, API-эндпоинты. Если имя HAR-файла заканчивается на .zip
, артефакты записываются как отдельные файлы и все сжимаются в один zip
.
# Сохранить API-запросы с example.com как архив "example.har".
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="open --save-har=example.har --save-har-glob='**/api/**' https://example.com"
Подробнее о продвинутой работе с сетью.
Мокирование WebSockets
Следующий код перехватит соединения WebSocket и замокирует всю коммуникацию через WebSocket, вместо подключения к серверу. Этот пример отвечает на "request"
с "response"
.
page.routeWebSocket("wss://example.com/ws", ws -> {
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
ws.send("response");
});
});
В качестве альтернативы, вы можете захотеть подключиться к реальному серверу, но перехватывать сообщения между ними и изменять или блокировать их. Вот пример, который изменяет некоторые из сообщений, отправляемых страницей на сервер, и оставляет остальные без изменений.
page.routeWebSocket("wss://example.com/ws", ws -> {
WebSocketRoute server = ws.connectToServer();
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
server.send("request2");
else
server.send(frame.text());
});
});
Для получения более подробной информации смотрите WebSocketRoute.