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

Выполнение JavaScript

Введение

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

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

href = page.evaluate('() => document.location.href')

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

status = page.evaluate("""async () => {
response = await fetch(location.href)
return response.status
}""")

Разные среды

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

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

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

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

data = "some data"
# Передайте |data| в качестве параметра.
result = page.evaluate("""data => {
window.myApp.use(data)
}""", data)

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

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

# Примитивное значение.
page.evaluate('num => num', 42)

# Массив.
page.evaluate('array => array.length', [1, 2, 3])

# Объект.
page.evaluate('object => object.foo', { 'foo': 'bar' })

# Один обработчик.
button = page.evaluate_handle('window.button')
page.evaluate('button => button.textContent', button)

# Альтернативная нотация с использованием JSHandle.evaluate.
button.evaluate('(button, from) => button.textContent.substring(from)', 5)

# Объект с несколькими обработчиками.
button1 = page.evaluate_handle('window.button1')
button2 = page.evaluate_handle('.button2')
page.evaluate("""o => o.button1.textContent + o.button2.textContent""",
{ 'button1': button1, 'button2': button2 })

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

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

# Любая смесь сериализуемых и обработчиков работает.
page.evaluate("""
x => x.button1.textContent + x.list[0].textContent + String(x.foo)""",
{ 'button1': button1, 'list': [button2], 'foo': None })

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

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

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

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

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

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

# В вашем тесте, предполагая, что файл "preload.js" находится в каталоге "mocks".
page.add_init_script(path="mocks/preload.js")