Сеть
Введение
Playwright предоставляет API для отслеживания и изменения трафика браузерной сети, как HTTP, так и HTTPS. Любые запросы, выполняемые страницей, включая XHR и fetch запросы, могут быть отслеживаются, изменены и обработаны.
Моделирование API
Ознакомьтесь с нашим руководством по моделированию API, чтобы узнать больше о том, как
- моделировать запросы к API и никогда не обращаться к API
- выполнять запрос к API и изменять ответ
- использовать файлы HAR для моделирования сетевых запросов.
Моделирование сети
Для моделирования сетевых запросов не нужно ничего настраивать. Просто определите пользовательский маршрут, который моделирует сеть для контекста браузера.
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ context }) => {
// Block any css requests for each test in this file.
await context.route(/.css$/, route => route.abort());
});
test('loads page without css', async ({ page }) => {
await page.goto('https://playwright.dev');
// ... test goes here
}); В качестве альтернативы можно использовать page.route(), чтобы моделировать сеть на отдельной странице.
import { test, expect } from '@playwright/test';
test('loads page without images', async ({ page }) => {
// Block png and jpeg images.
await page.route(/(png|jpeg)$/, route => route.abort());
await page.goto('https://playwright.dev');
// ... test goes here
}); HTTP-аутентификация
Выполните HTTP-аутентификацию.
- Тест
- Библиотека
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
httpCredentials: {
username: 'bill',
password: 'pa55w0rd',
}
}
});const context = await browser.newContext({
httpCredentials: {
username: 'bill',
password: 'pa55w0rd',
},
});
const page = await context.newPage();
await page.goto('https://example.com');HTTP-прокси
Вы можете настроить страницы для загрузки через HTTP(S)-прокси или SOCKSv5. Прокси можно установить глобально для всего браузера или для каждого контекста браузера индивидуально.
По желанию можно указать имя пользователя и пароль для HTTP(S)-прокси, а также хосты, для которых прокси нужно обойти.
Вот пример глобального прокси:
- Тест
- Библиотека
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
proxy: {
server: 'http://myproxy.com:3128',
username: 'usr',
password: 'pwd'
}
}
});const browser = await chromium.launch({
proxy: {
server: 'http://myproxy.com:3128',
username: 'usr',
password: 'pwd'
}
});Также можно указать его для каждого контекста:
- Тест
- Библиотека
import { test, expect } from '@playwright/test';
test('should use custom proxy on a new context', async ({ browser }) => {
const context = await browser.newContext({
proxy: {
server: 'http://myproxy.com:3128',
}
});
const page = await context.newPage();
await context.close();
});const browser = await chromium.launch();
const context = await browser.newContext({
proxy: { server: 'http://myproxy.com:3128' }
});Сетевые события
Вы можете отслеживать все запросы и ответы:
// Subscribe to 'request' and 'response' events.
page.on('request', request => console.log('>>', request.method(), request.url()));
page.on('response', response => console.log('<<', response.status(), response.url()));
await page.goto('https://example.com'); Или дождаться сетевого ответа после нажатия кнопки с помощью page.waitForResponse():
// Use a glob URL pattern. Note no await.
const responsePromise = page.waitForResponse('**/api/fetch_data');
await page.getByText('Update').click();
const response = await responsePromise; Варианты
Дождитесь ответов с помощью page.waitForResponse()
// Use a RegExp. Note no await.
const responsePromise = page.waitForResponse(/\.jpeg$/);
await page.getByText('Update').click();
const response = await responsePromise;
// Use a predicate taking a Response object. Note no await.
const responsePromise = page.waitForResponse(response => response.url().includes(token));
await page.getByText('Update').click();
const response = await responsePromise; Обработка запросов
await page.route('**/api/fetch_data', route => route.fulfill({
status: 200,
body: testData,
}));
await page.goto('https://example.com'); Вы можете моделировать конечные точки API, обрабатывая сетевые запросы в вашем скрипте Playwright.
Варианты
Настройте маршрут для всего контекста браузера с помощью browserContext.route() или страницы с помощью page.route(). Это будет применяться к всплывающим окнам и открытым ссылкам.
await browserContext.route('**/api/login', route => route.fulfill({
status: 200,
body: 'accept',
}));
await page.goto('https://example.com'); Изменение запросов
// Delete header
await page.route('**/*', async route => {
const headers = route.request().headers();
delete headers['X-Secret'];
await route.continue({ headers });
});
// Continue requests as POST.
await page.route('**/*', route => route.continue({ method: 'POST' })); Вы можете продолжить запросы с изменениями. В приведенном выше примере удаляется HTTP-заголовок из исходящих запросов.
Прерывание запросов
Вы можете прервать запросы, используя page.route() и route.abort().
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Abort based on the request type
await page.route('**/*', route => {
return route.request().resourceType() === 'image' ? route.abort() : route.continue();
}); Изменение ответов
Чтобы изменить ответ, используйте APIRequestContext, чтобы получить исходный ответ, а затем передайте ответ в route.fulfill(). Вы можете переопределить отдельные поля в ответе через параметры:
await page.route('**/title.html', async route => {
// Fetch original response.
const response = await route.fetch();
// Add a prefix to the title.
let body = await response.text();
body = body.replace('<title>', '<title>My prefix:');
await route.fulfill({
// Pass all fields from the response.
response,
// Override response body.
body,
// Force content type to be html.
headers: {
...response.headers(),
'content-type': 'text/html'
}
});
}); Шаблоны URL glob
Playwright использует упрощенные шаблоны glob для сопоставления URL в методах перехвата сети, таких как page.route() или page.waitForResponse(). Эти шаблоны поддерживают основные символы подстановки:
- Звездочки:
- Одна
*соответствует любым символам, кроме/ - Две
**соответствуют любым символам, включая/
- Одна
- Вопросительный знак
?соответствует любому одиночному символу, кроме/ - Фигурные скобки
{}могут использоваться для сопоставления списка вариантов, разделенных запятыми,
Примеры:
-
https://example.com/*.jsсоответствуетhttps://example.com/file.js, но неhttps://example.com/path/file.js -
**/*.jsсоответствуетhttps://example.com/file.jsиhttps://example.com/path/file.js -
**/*.{png,jpg,jpeg}соответствует всем запросам изображений
Важные замечания:
- Шаблон glob должен соответствовать всему URL, а не только его части.
- При использовании шаблонов glob для сопоставления URL учитывайте полную структуру URL, включая протокол и разделители путей.
- Для более сложных требований к сопоставлению используйте RegExp вместо шаблонов glob.
WebSocket
Playwright поддерживает проверку, моделирование и модификацию WebSocket «из коробки». Обратитесь к нашему руководству по моделированию API, чтобы узнать, как моделировать WebSocket.
Каждый раз, когда создается WebSocket, срабатывает событие page.on('websocket'). Это событие содержит экземпляр WebSocket для дальнейшей проверки кадров WebSocket:
page.on('websocket', ws => {
console.log(`WebSocket opened: ${ws.url()}>`);
ws.on('framesent', event => console.log(event.payload));
ws.on('framereceived', event => console.log(event.payload));
ws.on('close', () => console.log('WebSocket closed'));
}); Отсутствующие сетевые события и рабочие потоки
Встроенные в Playwright browserContext.route() и page.route() позволяют вашим тестам нативно маршрутизировать запросы и выполнять моделирование и перехват.
- Если вы используете встроенные в Playwright browserContext.route() и page.route(), и, похоже, сетевые события отсутствуют, отключите рабочие потоки, установив serviceWorkers в
'block'. - Возможно, вы используете инструмент моделирования, такой как Mock Service Worker (MSW). Хотя этот инструмент работает «из коробки» для моделирования ответов, он добавляет свой собственный рабочий поток, который берет на себя сетевые запросы, делая их невидимыми для browserContext.route() и page.route(). Если вас интересуют как тестирование сети, так и моделирование, рассмотрите использование встроенных browserContext.route() и page.route() для моделирования ответов.
- Если вас интересует не только использование Service Workers для тестирования и моделирования сети, но и маршрутизация и прослушивание запросов, выполняемых Service Workers, ознакомьтесь с этим экспериментальным функционалом.
© 2024 Microsoft
Licensed under the Apache License, Version 2.0.
https://playwright.dev/docs/network