Protractor — это фреймворк для end-to-end тестирования Angular и
AngularJS приложений. Основной особенностью Protractor является
встроенная поддержка асинхронной природы веб-приложений, что требует
особого подхода к синхронизации тестов. В основе лежит
концепция модели ожиданий (Expected Conditions) и
управление асинхронными операциями через Protractor Control
Flow или современные async/await.
В веб-тестировании часто встречаются ситуации, когда действия и проверки происходят быстрее, чем страница успевает загрузить элементы или обновить DOM. В Protractor такие случаи решаются через:
ExpectedConditions.Protractor по умолчанию интегрирован с Angular и умеет дожидаться
завершения асинхронных операций, что существенно упрощает написание
тестов. В AngularJS это реализуется через
browser.waitForAngular(), который вызывается автоматически
перед выполнением каждого действия.
ExpectedConditions — набор предопределённых условий,
которые можно использовать для explicit wait. Они
позволяют дожидаться состояния элемента или страницы перед выполнением
действий.
Примеры наиболее часто используемых условий:
Пример использования ExpectedConditions с явным
ожиданием:
const EC = protractor.ExpectedConditions;
const submitButton = element(by.id('submit'));
browser.wait(EC.elementToBeClickable(submitButton), 5000, 'Кнопка Submit не кликабельна');
submitButton.click();
Здесь browser.wait ждёт максимум 5 секунд до выполнения
клика. Если условие не выполнено, тест выбрасывает ошибку с указанным
сообщением.
Помимо ExpectedConditions, Protractor предоставляет
дополнительные возможности для контроля асинхронности:
Пример комбинированного подхода:
const EC = protractor.ExpectedConditions;
const alert = element(by.css('.alert-success'));
// дождаться появления элемента
browser.wait(EC.presenceOf(alert), 7000);
// проверить видимость и текст
expect(alert.isDisplayed()).toBe(true);
expect(alert.getText()).toContain('Успешно');
Современные версии Protractor поддерживают async/await,
что упрощает чтение и поддержку тестов, избавляя от необходимости
использования цепочек then().
Пример с async/await:
it('должен дождаться кликабельного элемента и нажать на него', async () => {
const EC = protractor.ExpectedConditions;
const loginButton = element(by.id('login'));
await browser.wait(EC.elementToBeClickable(loginButton), 5000);
await loginButton.click();
});
await автоматически приостанавливает выполнение до
завершения ожидания, что делает код линейным и более предсказуемым.
Protractor умеет работать с Angular приложениями по умолчанию. Для страниц, не использующих Angular, необходимо отключить автоматическую синхронизацию:
browser.waitForAngularEnabled(false);
browser.get('https://example.com/non-angular-page');
После выполнения действий на не-Angular странице рекомендуется снова включить синхронизацию:
browser.waitForAngularEnabled(true);
Это предотвращает потенциальные ошибки в последующих тестах.
Protractor позволяет создавать комплексные условия, комбинируя стандартные EC или создавая собственные:
const EC = protractor.ExpectedConditions;
const inputField = element(by.id('username'));
const submitButton = element(by.id('submit'));
// ожидание, пока поле не будет пустым и кнопка кликабельна
const customCondition = EC.and(
EC.textToBePresentInElementValue(inputField, 'admin'),
EC.elementToBeClickable(submitButton)
);
browser.wait(customCondition, 5000, 'Условие для поля и кнопки не выполнено');
Пользовательские условия оформляются как функции, возвращающие
Promise<boolean>, что позволяет максимально гибко
управлять синхронизацией.
ExpectedConditions для всех операций с
элементами, особенно кликов и ввода текста.browser.sleep(), применять
его только для отладки или крайних случаев.async/await для более линейного и читаемого
кода.Система ожиданий в Protractor обеспечивает надёжное управление асинхронностью и предотвращает большинство ошибок, связанных с попытками взаимодействия с элементами до их полной готовности на странице.