Protractor — инструмент для автоматизации тестирования веб-приложений на основе Angular и AngularJS, но его возможности распространяются и на обычные веб-приложения. Одной из ключевых особенностей Protractor является умение работать с асинхронными процессами и ожидать завершения выполнения JavaScript в браузере. Это критично для корректного взаимодействия с динамическим контентом и современными SPA (Single Page Application).
Protractor изначально создан для Angular-приложений. Он использует
механизм automatic synchronization, который позволяет
тесту ожидать завершения всех асинхронных операций Angular перед
выполнением действий. В основе лежит метод
browser.waitForAngular(), который автоматически вызывается
перед выполнением команд, таких как element.click() или
element.getText().
Пример:
element(by.css('.submit-button')).click();
// Перед кликом Protractor проверяет, что все $http и $timeout завершены
Если приложение не использует Angular, необходимо явно отключить синхронизацию:
browser.waitForAngularEnabled(false);
После этого Protractor перестает ждать автоматические завершения Angular и управление полностью переходит к ручным ожиданиям.
browser.executeScript()Для выполнения кастомного JavaScript кода в браузере используется
метод browser.executeScript(). Он возвращает
Promise, который разрешается после завершения
выполнения скрипта. Это позволяет интегрировать произвольные проверки
или манипуляции с DOM.
Пример:
browser.executeScript('return document.readyState')
.then(state => {
console.log('Текущее состояние страницы:', state);
});
Этот метод особенно полезен для проверки готовности нестандартных элементов или выполнения скриптов, которые Protractor не отслеживает автоматически.
browser.wait()Для случаев, когда необходимо дождаться выполнения определённого
условия на странице, используется browser.wait(). Метод
принимает функцию-условие и таймаут:
const EC = protractor.ExpectedConditions;
const button = element(by.id('load-data'));
browser.wait(EC.elementToBeClickable(button), 5000);
button.click();
Здесь ExpectedConditions предоставляет набор готовых
проверок, таких как видимость элемента, кликабельность или присутствие
текста. Таймаут указывается в миллисекундах, и если условие не
выполнено, тест завершится ошибкой.
Иногда требуется дождаться выполнения конкретного JavaScript-кода,
например, AJAX-запроса или завершения анимации. Для этого можно
использовать browser.executeAsyncScript():
browser.executeAsyncScript(function(callback) {
setTimeout(() => {
callback('готово');
}, 2000);
}).then(result => {
console.log(result); // 'готово'
});
Отличие от executeScript() заключается в том, что
функция принимает callback, который должен быть вызван
после завершения асинхронного кода. Protractor автоматически ожидает
вызова этого callback, что позволяет синхронизировать тест с
динамическими процессами.
В современных веб-приложениях элементы часто появляются или исчезают
динамически. Использование комбинации ExpectedConditions и
browser.wait() позволяет минимизировать ошибки:
const EC = protractor.ExpectedConditions;
const dynamicElement = element(by.css('.dynamic-element'));
browser.wait(EC.presenceOf(dynamicElement), 10000)
.then(() => dynamicElement.getText())
.then(text => console.log(text));
Такой подход обеспечивает стабильность тестов и исключает ситуации, когда действия выполняются до появления элементов на странице.
Protractor позволяет глобально и локально настраивать таймауты ожидания Jav * aScript:
browser.manage().timeouts().implicitlyWait(5000); // 5 секунд
browser.wait(EC.visibilityOf(element(by.id('message'))), 7000);
Использование правильных таймаутов критично для балансировки между стабильностью тестов и их скоростью выполнения.
executeAsyncScript() с callback.ExpectedConditions и browser.wait().browser.sleep(), так как это
снижает стабильность тестов и увеличивает время их выполнения.Эффективное ожидание выполнения JavaScript в Protractor обеспечивает надежность тестов, минимизирует ложные ошибки и позволяет работать с современными динамическими веб-интерфейсами.