В автоматизированном тестировании веб-приложений на Angular критически важно учитывать асинхронность фреймворка. Angular управляет большим количеством внутренних процессов — таких как обработка событий, рендеринг шаблонов и HTTP-запросы. Для корректного взаимодействия с элементами страницы необходимо убедиться, что Angular завершил все свои задачи. Protractor предоставляет встроенные механизмы для отслеживания готовности Angular, что является одной из его ключевых особенностей.
Protractor расширяет Selenium WebDriver, добавляя интеграцию с Angular. Основная идея заключается в том, что тесты автоматически ожидают завершения всех асинхронных операций Angular перед взаимодействием с элементами страницы. Это достигается через механизм waiting for Angular, который использует следующие методы Angular:
Когда Protractor открывает страницу Angular, он автоматически активирует эти механизмы, если включен режим синхронизации.
По умолчанию Protractor синхронизируется с Angular на каждой странице. Этот процесс управляется флагом:
browser.waitForAngularEnabled(true);
Примеры использования:
// Включение ожидания Angular
browser.waitForAngularEnabled(true);
// Отключение ожидания (например, для не-Angular страниц)
browser.waitForAngularEnabled(false);
Важно помнить, что для страниц, не использующих Angular, автоматическое ожидание приведет к зависанию теста, так как Protractor будет ожидать событий Angular, которых нет.
Protractor использует ExpectedConditions для проверки состояния элементов, но внутри Angular-страниц можно полагаться на автоматическое ожидание готовности Angular:
const EC = protractor.ExpectedConditions;
let button = element(by.id('submit'));
browser.wait(EC.elementToBeClickable(button), 5000);
button.click();
Однако, если страница активно взаимодействует с асинхронными сервисами Angular, это может быть недостаточно. В таких случаях используется browser.waitForAngular():
// Явное ожидание завершения всех задач Angular
browser.waitForAngular().then(() => {
button.click();
});
Метод waitForAngular() гарантирует, что все
$http-запросы и таймеры завершены, и состояние приложения стабильно.
Часто в приложении есть страницы или виджеты, не зависящие от Angular. В таких ситуациях необходимо временно отключать синхронизацию:
browser.waitForAngularEnabled(false);
browser.get('https://example.com/non-angular');
element(by.css('.login')).click();
После работы с не-Angular страницей синхронизация возвращается:
browser.waitForAngularEnabled(true);
Это предотвращает зависания и ошибки тестов, вызванные ожиданием событий Angular там, где их нет.
Angular использует промисы и внутренние таймеры, что иногда требует явного ожидания в тестах:
element(by.model('username')).sendKeys('user');
element(by.model('password')).sendKeys('pass');
// Явное ожидание Angular перед кликом
browser.waitForAngular().then(() => {
element(by.id('login')).click();
});
Protractor также автоматически отслеживает промисы, возвращаемые Angular-сервисами, что снижает необходимость ручного управления асинхронностью.
Важным аспектом работы с ожиданием Angular является таймаут
ожидания. Он настраивается через allScriptsTimeout
в конфигурации Protractor:
exports.config = {
allScriptsTimeout: 11000, // Время ожидания выполнения скриптов Angular
getPageTimeout: 10000
};
allScriptsTimeout – максимальное время ожидания
завершения всех асинхронных операций Angular.getPageTimeout – максимальное время ожидания загрузки
страницы.Правильная настройка этих параметров снижает вероятность ошибок из-за долгих HTTP-запросов или тяжелого рендеринга.
browser.waitForAngular() после
загрузки модуля.waitForAngular() здесь особенно важно.waitForAngularEnabled(true) для страниц
Angular.browser.waitForAngular() перед действиями
с элементами, если приложение активно загружает данные асинхронно.allScriptsTimeout и
getPageTimeout в зависимости от скорости приложения.ExpectedConditions для надежной работы тестов.Эффективное управление ожиданием Angular обеспечивает стабильность тестов, предотвращает ошибки взаимодействия с элементами и позволяет полностью использовать преимущества Protractor при автоматизации современных Angular-приложений.