Protractor — это инструмент для end-to-end тестирования приложений на
Angular и не только. Ключевой задачей является взаимодействие с
элементами страницы: поиск, навигация, ожидание и выполнение действий. В
основе работы лежит WebDriverJS, что обеспечивает синхронизацию с
браузером и управляемую асинхронность через
async/await.
Поиск элементов осуществляется через объект element и
локаторы из модуля by.
Основные локаторы:
const usernameInput = element(by.id('username'));
const submitButton = element(by.css('.submit-button'));
const menuItems = element.all(by.tagName('li'));
const link = element(by.linkText('Home'));
const partialLink = element(by.partialLinkText('Hom'));
by.id — уникальный идентификатор
элемента.by.css — CSS-селектор для гибкой
навигации.by.tagName — поиск по имени тега.by.className — поиск по имени
класса.by.name — поиск по атрибуту
name.by.linkText и
by.partialLinkText — поиск ссылок по тексту.Для множественных элементов используется element.all()
вместо element(), что возвращает
ElementArrayFinder. Он поддерживает методы фильтрации и
индексирования.
const buttons = element.all(by.css('.btn'));
const firstButton = buttons.first();
const lastButton = buttons.last();
const thirdButton = buttons.get(2);
После нахождения элемента можно выполнять цепочку действий и навигацию:
const form = element(by.css('form#loginForm'));
const input = form.element(by.css('input[name="email"]'));
const items = element.all(by.css('.item'));
const activeItems = items.filter(async (elem) => {
const cls = await elem.getAttribute('class');
return cls.includes('active');
});
const secondItem = items.get(1); // нумерация с нуля
xpath:const header = element(by.xpath('//h1[contains(text(), "Welcome")]'));
XPath полезен для сложной логики поиска, когда
CSS-селекторы ограничены.
Protractor построен на WebDriverJS, который возвращает
промисы. Для синхронного кода применяется async/await:
const username = element(by.id('username'));
await username.sendKeys('user123');
const button = element(by.css('.submit-button'));
await button.click();
Методы getText(), getAttribute(),
isDisplayed() и другие также возвращают промисы:
const text = await element(by.css('.message')).getText();
const visible = await element(by.css('.alert')).isDisplayed();
Эффективная навигация требует ожидания состояния элементов.
Protractor предоставляет ExpectedConditions:
const EC = protractor.ExpectedConditions;
const submitButton = element(by.css('.submit-button'));
// Ожидание, пока кнопка станет кликабельной
await browser.wait(EC.elementToBeClickable(submitButton), 5000);
await submitButton.click();
Основные условия:
elementToBeClickable(element) — элемент доступен для
клика.visibilityOf(element) — элемент видим.presenceOf(element) — элемент присутствует в DOM.textToBePresentInElement(element, text) — проверка
текста.Элементы можно комбинировать для сложной логики:
const rows = element.all(by.css('table#users tr'));
const activeUserNames = rows.filter(async (row) => {
const status = await row.element(by.css('.status')).getText();
return status === 'Active';
}).map(async (row) => {
return row.element(by.css('.name')).getText();
});
В этом примере используется фильтрация по состоянию и извлечение текста для коллекции.
Для элементов внутри iframe требуется переключение
контекста:
const frame = element(by.css('iframe#editor'));
await browser.switchTo().frame(frame.getWebElement());
const editor = element(by.css('.editor-content'));
await editor.sendKeys('Текст в iframe');
await browser.switchTo().defaultContent(); // возвращение к основному DOM
ExpectedConditions
вместо sleep.element.all()
и методы фильтрации.await.Эти подходы обеспечивают точное и надежное управление элементами на странице, позволяя строить устойчивые end-to-end тесты для веб-приложений.