Поиск конкретной строки

В автоматизированном тестировании веб-приложений на JavaScript с использованием Protractor часто возникает задача найти конкретный текст на странице. Protractor, построенный поверх Selenium WebDriver, предоставляет мощные механизмы для поиска элементов и проверки их содержимого. Эффективная работа с текстовыми значениями позволяет создавать надежные и точные тесты.


Использование element и by для поиска текста

Базовая единица работы в Protractor — объект ElementFinder. Для поиска конкретного текста применяются локаторы, предоставляемые объектом by:

element(by.css('selector')).getText().then(text => {
    if (text === 'Искомая строка') {
        console.log('Строка найдена');
    }
});

Пояснения:

  • element возвращает первый найденный элемент, соответствующий локатору.
  • by.css — универсальный CSS-селектор.
  • getText() извлекает текстовое содержимое элемента.
  • Метод then() используется для обработки промиса, так как getText() возвращает промис.

Локатор by.xpath для поиска текста внутри элементов

XPath позволяет выполнять поиск элементов с конкретным текстом без необходимости сначала получать все элементы. Пример:

let targetElement = element(by.xpath("//*[text()='Искомая строка']"));
expect(targetElement.isPresent()).toBe(true);

Ключевые моменты:

  • //*[text()='Искомая строка'] — ищет любой элемент с точным совпадением текста.
  • isPresent() проверяет существование элемента на странице.
  • Этот метод эффективен для динамически создаваемого контента, где сложно заранее определить уникальный CSS-селектор.

Поиск по частичному тексту

Для поиска элементов, содержащих текст частично, удобно использовать contains() в XPath:

let partialMatch = element(by.xpath("//*[contains(text(),'часть строки')]"));
expect(partialMatch.isDisplayed()).toBe(true);

Особенности:

  • contains(text(),'часть строки') находит все элементы, текст которых включает указанную подстроку.
  • Метод isDisplayed() проверяет видимость элемента, что полезно для проверки интерфейса.

Поиск среди множества элементов

Иногда текст необходимо найти среди коллекции элементов. Для этого используется ElementArrayFinder:

let items = element.all(by.css('.list-item'));
items.filter(async (elem) => {
    let text = await elem.getText();
    return text.includes('Искомая строка');
}).then(filteredElements => {
    console.log('Найдено элементов:', filteredElements.length);
});

Пояснения:

  • element.all возвращает массив элементов.
  • filter позволяет оставить только те элементы, которые соответствуют условию.
  • Асинхронная функция внутри фильтра обеспечивает корректное получение текста каждого элемента.

Применение регулярных выражений

Для гибкого поиска текста можно использовать регулярные выражения:

let regex = /Искомая\sстрока/i;
element.all(by.css('.list-item')).filter(async (elem) => {
    let text = await elem.getText();
    return regex.test(text);
}).then(matches => {
    console.log('Совпадений с регулярным выражением:', matches.length);
});

Преимущества:

  • Возможность поиска без точного совпадения регистра или с учетом вариаций текста.
  • Подходит для сложных сценариев тестирования динамических интерфейсов.

Асинхронное ожидание появления текста

Текст может появляться с задержкой из-за асинхронной загрузки данных. Для таких случаев используется ExpectedConditions:

const EC = protractor.ExpectedConditions;
let elementToWait = element(by.css('.notification'));

browser.wait(EC.textToBePresentInElement(elementToWait, 'Искомая строка'), 5000);

Комментарии:

  • textToBePresentInElement проверяет, появился ли текст в элементе.
  • Второй аргумент 5000 — максимальное время ожидания в миллисекундах.
  • Это предотвращает ложные отрицательные результаты при динамическом контенте.

Использование кастомной функции поиска

Для сложных случаев, например, при необходимости искать текст в нескольких элементах с разной структурой, удобно писать собственные функции:

async function findElementByText(elements, searchText) {
    for (let i = 0; i < await elements.count(); i++) {
        let elem = elements.get(i);
        let text = await elem.getText();
        if (text.includes(searchText)) {
            return elem;
        }
    }
    return null;
}

let items = element.all(by.css('.list-item'));
let target = await findElementByText(items, 'Искомая строка');
if (target) {
    console.log('Элемент найден');
}

Особенности подхода:

  • Позволяет гибко управлять логикой поиска.
  • Можно интегрировать дополнительные условия, например проверку атрибутов или видимости элемента.

Советы по оптимизации поиска текста

  • По возможности использовать точные селекторы (id, class) для минимизации объема DOM-обхода.
  • Предпочтение отдавать методам isPresent и isDisplayed для проверки существования и видимости элементов вместо попытки получить текст всех элементов.
  • Для динамических страниц использовать ExpectedConditions для корректного ожидания появления текста.
  • Регулярные выражения упрощают поиск с вариациями текста, сокращая количество фильтров.

Эти методы позволяют эффективно находить конкретные строки в DOM-структуре, обеспечивая надежность тестов и упрощая работу с динамическим контентом в приложениях на Angular и других фронтенд-фреймворках.