Handles
Введение
Playwright может создавать ссылки на элементы DOM страницы или любые другие объекты внутри страницы. Эти ссылки существуют в процессе Playwright, тогда как реальные объекты находятся в браузере. Существует два типа ссылок:
- JSHandle для ссылки на любые JavaScript объекты на странице
- ElementHandle для ссылки на элементы DOM на странице, он имеет дополнительные методы, которые позволяют выполнять действия с элементами и проверять их свойства.
Поскольку любой элемент DOM на странице также является JavaScript объектом, любой ElementHandle также является JSHandle.
Ссылки используются для выполнения операций с этими реальными объектами на странице. Вы можете выполнять вычисления на ссылке, получать свойства ссылки, передавать ссылку в качестве параметра вычисления, сериализовать объект страницы в JSON и т.д. См. API класса JSHandle для этих и других методов.
Справочник API
Вот самый простой способ получить JSHandle.
const jsHandle = await page.evaluateHandle('window');
// Используйте jsHandle для вычислений.
Ссылки на элементы
Использование ElementHandle не рекомендуется, вместо этого используйте объекты Locator и утверждения, ориентированные на веб.
Когда требуется ElementHandle, рекомендуется получать его с помощью методов page.waitForSelector() или frame.waitForSelector(). Эти API ожидают, пока элемент будет прикреплен и видим.
// Получите ссылку на элемент
const elementHandle = page.waitForSelector('#box');
// Проверьте ограничивающий прямоугольник элемента
const boundingBox = await elementHandle.boundingBox();
expect(boundingBox.width).toBe(100);
// Проверьте атрибут элемента
const classNames = await elementHandle.getAttribute('class');
expect(classNames.includes('highlighted')).toBeTruthy();
Ссылки в качестве параметров
Ссылки могут быть переданы в методы page.evaluate() и аналогичные. Следующий фрагмент создает новый массив на странице, инициализирует его данными и возвращает ссылку на этот массив в Playwright. Затем он использует ссылку в последующих вычислениях:
// Создайте новый массив на странице.
const myArrayHandle = await page.evaluateHandle(() => {
window.myArray = [1];
return myArray;
});
// Получите длину массива.
const length = await page.evaluate(a => a.length, myArrayHandle);
// Добавьте еще один элемент в массив, используя ссылку
await page.evaluate(arg => arg.myArray.push(arg.newElement), {
myArray: myArrayHandle,
newElement: 2
});
// Освободите объект, когда он больше не нужен.
await myArrayHandle.dispose();
Жизненный цикл ссылок
Ссылки могут быть получены с помощью методов страницы, таких как page.evaluateHandle(), page.$() или page.$$() или их аналогов для фреймов frame.evaluateHandle(), frame.$() или frame.$$(). После создания ссылки будут удерживать объект от сборки мусора, если только страница не навигируется или ссылка не удаляется вручную с помощью метода jsHandle.dispose().
Справочник API
- JSHandle
- ElementHandle
- elementHandle.boundingBox()
- elementHandle.getAttribute()
- elementHandle.innerText()
- elementHandle.innerHTML()
- elementHandle.textContent()
- jsHandle.evaluate()
- page.evaluateHandle()
- page.$()
- page.$$()
Locator vs ElementHandle
Мы рекомендуем использовать ElementHandle только в редких случаях, когда вам нужно выполнить обширный обход DOM на статической странице. Для всех пользовательских действий и утверждений используйте локатор.
Разница между Locator и ElementHandle заключается в том, что последний указывает на конкретный элемент, в то время как Locator захватывает логику того, как получить этот элемент.
В примере ниже, ссылка указывает на конкретный элемент DOM на странице. Если этот элемент изменяет текст или используется React для рендеринга совершенно другого компонента, ссылка все равно указывает на этот устаревший элемент DOM. Это может привести к неожиданным поведением.
const handle = await page.$('text=Submit');
// ...
await handle.hover();
await handle.click();
С локатором, каждый раз, когда он используется, актуальный элемент DOM находится на странице с использованием селектора. Таким образом, в приведенном ниже фрагменте, подлежащий элемент DOM будет найден дважды.
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();