Перейти к основному содержимому

Выполнение JavaScript

Введение

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

API Page.EvaluateAsync() может выполнять JavaScript-функцию в контексте веб-страницы и возвращать результаты в среду Playwright. Глобальные объекты браузера, такие как window и document, могут использоваться в evaluate.

var href = await page.EvaluateAsync<string>("document.location.href");

Если результат является Promise или если функция асинхронная, evaluate автоматически дождется ее разрешения:

int status = await page.EvaluateAsync<int>(@"async () => {
const response = await fetch(location.href);
return response.status;
}");

Разные среды

Выполняемые скрипты работают в среде браузера, в то время как ваш тест выполняется в тестовой среде. Это означает, что вы не можете использовать переменные из вашего теста на странице и наоборот. Вместо этого вы должны передавать их явно в качестве аргумента.

Следующий фрагмент НЕПРАВИЛЬНЫЙ, потому что он использует переменную напрямую:

var data = "some data";
var result = await page.EvaluateAsync(@"() => {
// НЕПРАВИЛЬНО: на веб-странице нет 'data'.
window.myApp.use(data);
}");

Следующий фрагмент ПРАВИЛЬНЫЙ, потому что он передает значение явно в качестве аргумента:

var data = "some data";
// Передаем |data| как параметр.
var result = await page.EvaluateAsync("data => { window.myApp.use(data); }", data);

Аргумент для выполнения

Методы выполнения Playwright, такие как Page.EvaluateAsync(), принимают один необязательный аргумент. Этот аргумент может быть смесью значений Serializable и экземпляров JSHandle. Обработчики автоматически преобразуются в представляемое ими значение.

// Примитивное значение.
await page.EvaluateAsync<int>("num => num", 42);

// Массив.
await page.EvaluateAsync<int[]>("array => array.length", new[] { 1, 2, 3 });

// Объект.
await page.EvaluateAsync<object>("object => object.foo", new { foo = "bar" });

// Один обработчик.
var button = await page.EvaluateHandleAsync("window.button");
await page.EvaluateAsync<IJSHandle>("button => button.textContent", button);

// Альтернативная нотация с использованием JSHandle.EvaluateAsync.
await button.EvaluateAsync<string>("(button, from) => button.textContent.substring(from)", 5);

// Объект с несколькими обработчиками.
var button1 = await page.EvaluateHandleAsync("window.button1");
var button2 = await page.EvaluateHandleAsync("window.button2");
await page.EvaluateAsync("o => o.button1.textContent + o.button2.textContent", new { button1, button2 });

// Деструктуризация объекта работает. Обратите внимание, что имена свойств должны совпадать
// между деструктурированным объектом и аргументом.
// Также обратите внимание на обязательные скобки.
await page.EvaluateAsync("({ button1, button2 }) => button1.textContent + button2.textContent", new { button1, button2 });

// Массив также работает. Можно использовать произвольные имена для деструктуризации.
// Обратите внимание на обязательные скобки.
await page.EvaluateAsync("([b1, b2]) => b1.textContent + b2.textContent", new[] { button1, button2 });

// Любая смесь сериализуемых и обработчиков работает.
await page.EvaluateAsync("x => x.button1.textContent + x.list[0].textContent + String(x.foo)", new { button1, list = new[] { button2 }, foo = null as object });

Скрипты инициализации

Иногда удобно выполнить что-то на странице до того, как она начнет загружаться. Например, вы можете захотеть настроить некоторые моки или тестовые данные.

В этом случае используйте Page.AddInitScriptAsync() или BrowserContext.AddInitScriptAsync(). В примере ниже мы заменим Math.random() на постоянное значение.

Сначала создайте файл preload.js, содержащий мок.

// preload.js
Math.random = () => 42;

Затем добавьте скрипт инициализации на страницу.

// В вашем тесте, предполагая, что файл "preload.js" находится в директории "mocks".
await Page.AddInitScriptAsync(scriptPath: "mocks/preload.js");