Protractor — инструмент для end-to-end тестирования Angular и не-Angular приложений на JavaScript. Одной из ключевых особенностей является работа с возвращаемыми значениями элементов страницы, асинхронными операциями и ожиданиями. Понимание механизма получения данных из элементов и работы с промисами критично для написания корректных и стабильных тестов.
Метод element(locator) возвращает объект
ElementFinder, который не содержит напрямую значения
элемента. Чтобы получить текст или атрибут, необходимо использовать
методы, возвращающие промис:
let username = element(by.id('username'));
// Получение текста элемента
username.getText().then(text => {
console.log('Текст элемента:', text);
});
// Получение атрибута
username.getAttribute('value').then(value => {
console.log('Значение атрибута:', value);
});
Ключевой момент: getText() и getAttribute()
всегда возвращают промис. В Protractor 5 и старше использовались методы
then() для обработки. В современных версиях с поддержкой
async/await код становится более читаемым:
let text = await username.getText();
let value = await username.getAttribute('value');
Любое взаимодействие с элементами на странице, будь то
click(), sendKeys() или
getText(), является асинхронным. Protractor изначально
использовал control flow, который позволял писать код
без явного ожидания промисов, но начиная с последних версий
рекомендуется использовать async/await для контроля
последовательности действий.
Пример асинхронной цепочки:
let loginButton = element(by.css('.login-button'));
let username = element(by.id('username'));
let password = element(by.id('password'));
await username.sendKeys('testuser');
await password.sendKeys('securepassword');
await loginButton.click();
let successMessage = element(by.css('.success')).getText();
console.log(await successMessage); // вывод текста после клика
ElementArrayFinderДля работы с множественными элементами применяется
element.all(locator), возвращающий объект
ElementArrayFinder. Основные методы:
get(index) — получение конкретного элемента по
индексу.first() / last() — доступ к первому и
последнему элементу.count() — количество найденных элементов.map(fn) — преобразование массива элементов в массив
значений.Пример:
let items = element.all(by.css('.item'));
let firstItemText = await items.first().getText();
let lastItemText = await items.last().getText();
let itemCount = await items.count();
console.log(`Всего элементов: ${itemCount}`);
console.log(`Первый элемент: ${firstItemText}`);
console.log(`Последний элемент: ${lastItemText}`);
Метод map() позволяет получить массив данных всех
элементов:
let texts = await items.map(async el => await el.getText());
console.log(texts); // массив текстов всех элементов
Все методы ElementFinder и
ElementArrayFinder возвращают promise. Для
правильной работы необходимо использовать:
await (современный подход).then() для старых версийНеправильное обращение к промису может привести к тому, что переменная будет содержать не значение элемента, а объект промиса:
let textPromise = element(by.id('header')).getText();
console.log(textPromise); // [object Promise], а не текст
Правильно:
let text = await element(by.id('header')).getText();
console.log(text); // корректный вывод текста
При получении значений с элементов важно учитывать, что элемент может
быть еще не загружен или не видим. Использование
ExpectedConditions помогает гарантировать получение
корректных данных:
let EC = protractor.ExpectedConditions;
let message = element(by.css('.message'));
await browser.wait(EC.visibilityOf(message), 5000);
let text = await message.getText();
console.log(text);
Ожидания предотвращают ошибки, связанные с попыткой прочитать текст до того, как элемент появился на странице.
Иногда текст или атрибут необходимо преобразовать перед использованием:
let priceText = await element(by.css('.price')).getText();
let priceNumber = parseFloat(priceText.replace('$', ''));
console.log(priceNumber);
Аналогично можно фильтровать массив значений:
let items = element.all(by.css('.item'));
let prices = await items.map(async el => {
let text = await el.getText();
return parseFloat(text.replace('$', ''));
});
let expensiveItems = prices.filter(p => p > 50);
console.log(expensiveItems);
Методы вроде isDisplayed(), isEnabled(),
isSelected() возвращают промис, который резолвится в
true или false. Пример:
let submitButton = element(by.id('submit'));
let enabled = await submitButton.isEnabled();
if (enabled) {
await submitButton.click();
}
Эти методы полезны для проверки состояния элементов до взаимодействия.
await при работе с
возвращаемыми значениями, чтобы избежать неожиданностей.isPresent() или count() перед попыткой
прочитать текст.map и filter
для обработки массивов элементов и получения удобных массивов
данных.Эффективная работа с возвращаемыми значениями позволяет писать
стабильные, читаемые тесты и полностью контролировать асинхронное
поведение веб-страницы. Правильное использование await,
ожиданий и методов
ElementFinder/ElementArrayFinder делает тесты
предсказуемыми и уменьшает вероятность ошибок, связанных с
асинхронностью и динамическим контентом.