Protractor — это инструмент для end-to-end тестирования Angular и не-Angular приложений на JavaScript. Он основан на Selenium WebDriver и предоставляет расширенные возможности для работы с асинхронными операциями, характерными для современных веб-приложений.
Для начала работы необходимо установить Protractor через npm:
npm install -g protractor
После установки доступна команда protractor --version
для проверки корректности установки. Также требуется запуск Selenium
Server:
webdriver-manager update
webdriver-manager start
Конфигурация тестов осуществляется через файл
protractor.conf.js, где указываются браузеры, пути к
тестам, тайм-ауты и другие настройки:
exports.config = {
directConnect: true,
framework: 'jasmine',
specs: ['specs/**/*.spec.js'],
capabilities: {
browserName: 'chrome'
},
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};
Ключевой момент: использование
directConnect: true позволяет обойти запуск отдельного
Selenium Server и напрямую управлять браузером.
Protractor использует WebDriverJS, поэтому элементы страницы выбираются с помощью локаторов:
let usernameInput = element(by.id('username'));
let loginButton = element(by.css('.login-button'));
let items = element.all(by.repeater('item in items'));
element(by.id('...')) — выбор одного элемента по
ID.element(by.css('...')) — выбор элемента по
CSS-селектору.element.all(by.repeater('...')) — выбор группы
элементов в Angular repeater.Особенность: element.all возвращает
массив объектов ElementArrayFinder, с которыми можно работать через
методы get(index), first(),
last() и count().
Protractor поддерживает работу с промисами через async/await. Это особенно важно при взаимодействии с элементами страницы:
it('должен вводить логин и нажимать кнопку', async () => {
await usernameInput.sendKeys('admin');
await loginButton.click();
});
Принципиально: все действия с элементами требуют
await, чтобы убедиться в завершении операции перед
следующей командой.
Метод browser.get(url) открывает указанный URL:
await browser.get('https://example.com/login');
Для возврата на предыдущую страницу используется:
await browser.navigate().back();
Прямая навигация и возврат позволяют создавать сценарии с проверкой истории браузера.
Для стабильных тестов крайне важно использовать ожидания:
let EC = protractor.ExpectedConditions;
await browser.wait(EC.visibilityOf(loginButton), 5000, 'Кнопка не появилась');
visibilityOf — ожидает появления элемента.elementToBeClickable — ожидает, пока элемент станет
кликабельным.Рекомендация: не использовать жесткие задержки
browser.sleep(), они увеличивают время выполнения и делают
тесты нестабильными.
Protractor позволяет эффективно работать с формами:
await element(by.model('user.name')).sendKeys('Иван');
await element(by.model('user.password')).sendKeys('123456');
await element(by.buttonText('Войти')).click();
by.model используется для Angular-привязки данных.by.buttonText и by.partialButtonText
позволяют выбрать кнопку по тексту.Важно: использование Angular локаторов
(by.model, by.binding) делает тесты более
устойчивыми к изменению DOM.
Protractor интегрируется с Jasmine, предоставляя средства для проверок:
let successMessage = element(by.css('.success'));
expect(await successMessage.getText()).toEqual('Вход выполнен успешно');
expect(await loginButton.isEnabled()).toBe(true);
getText() возвращает текст элемента.isDisplayed() проверяет видимость.isEnabled() проверяет доступность элемента для
взаимодействия.Для работы с массивами элементов:
let items = element.all(by.repeater('item in items'));
expect(await items.count()).toBe(5);
expect(await items.get(0).getText()).toContain('Первый элемент');
Protractor позволяет управлять alert и confirm:
await browser.switchTo().alert().accept();
await browser.switchTo().alert().dismiss();
let alertText = await browser.switchTo().alert().getText();
Подсказка: при работе с модальными окнами нужно
всегда переключаться через browser.switchTo().alert() перед
взаимодействием.
Для крупных проектов рекомендуется организовать тесты в папки:
/specs
login.spec.js
dashboard.spec.js
/pages
login.page.js
dashboard.page.js
Стратегия Page Object Model (POM):
/pages содержит методы для взаимодействия
с элементами страницы.spec.js) используют эти методы, повышая
читаемость и переиспользуемость.Пример Page Object:
class LoginPage {
constructor() {
this.usernameInput = element(by.id('username'));
this.passwordInput = element(by.id('password'));
this.loginButton = element(by.buttonText('Войти'));
}
async login(user, pass) {
await this.usernameInput.sendKeys(user);
await this.passwordInput.sendKeys(pass);
await this.loginButton.click();
}
}
module.exports = new LoginPage();
Protractor поддерживает вывод логов:
browser.manage().logs().get('browser').then(function(logs) {
logs.forEach(function(log) {
console.log(log.message);
});
});
Для детальной отладки можно включить
SELENIUM_PROMISE_MANAGER: false в конфигурации и
использовать async/await для пошагового контроля выполнения
тестов.
Особенность многих Angular-приложений — динамическое обновление контента и всплывающие окна. Для возврата к главному содержимому используется комбинация навигации и ожиданий:
await browser.navigate().back();
let mainContent = element(by.id('main-content'));
await browser.wait(protractor.ExpectedConditions.visibilityOf(mainContent), 5000);
Такой подход гарантирует, что после перехода пользователь окажется именно на основной странице, а тест не продолжится, пока контент полностью не загрузится.
Ключевой принцип: всегда сочетать навигацию с ожиданием элементов, чтобы избежать нестабильных тестов и ошибок, связанных с асинхронной загрузкой страницы.