Работа с ng-repeat структурами

AngularJS активно использует директиву ng-repeat для генерации списков элементов на основе массива данных. В тестировании таких структур возникает необходимость взаимодействия с каждым элементом списка, проверки их содержимого, состояния или выполнения действий на конкретных элементах. Protractor предоставляет специализированные возможности для работы с ng-repeat, позволяя писать надежные и читаемые тесты.


Локаторы by.repeater

Основной инструмент для работы с ng-repeat — локатор by.repeater. Он позволяет находить элементы, которые создаются повторением по массиву. Синтаксис:

element.all(by.repeater('item in items'));

Здесь 'item in items' — это точная запись из Angular-шаблона. Важно использовать идентичное имя переменной и коллекции, как в HTML-шаблоне.

Методы, доступные для работы с repeater:

  • element.all(by.repeater('item in items')) — возвращает коллекцию всех элементов.
  • get(index) — получает элемент по индексу.
  • first() / last() — получение первого и последнего элементов.
  • count() — подсчет элементов в коллекции.
  • map(fn) — применение функции к каждому элементу списка.

Пример использования:

const items = element.all(by.repeater('item in items'));
expect(items.count()).toEqual(5);

const firstItem = items.first();
expect(firstItem.getText()).toContain('Первый элемент');

Доступ к дочерним элементам внутри ng-repeat

Очень часто требуется получить не весь элемент, а отдельные поля или кнопки внутри него. Protractor позволяет комбинировать локаторы:

const items = element.all(by.repeater('item in items'));
const firstItemButton = items.first().element(by.css('.delete-btn'));
firstItemButton.click();

Использование метода element() на элементе из коллекции позволяет точечно работать с вложенными элементами, что особенно важно при сложных шаблонах AngularJS.


Получение данных из ng-repeat

Для проверки данных внутри ng-repeat удобно использовать метод getText() или getAttribute():

const itemTexts = items.map(item => item.getText());
itemTexts.then(texts => {
  expect(texts).toContain('Элемент 3');
});

Метод map() возвращает промисы для всех элементов, что позволяет легко проверять массивы данных.

Для конкретного свойства Angular-модели можно использовать evaluate():

const firstItem = element(by.repeater('item in items').row(0));
expect(firstItem.evaluate('item.name')).toEqual('Item 1');

Метод evaluate() вычисляет выражение Angular в контексте конкретного элемента ng-repeat. Это особенно полезно, когда требуется проверить модель напрямую, а не текстовое представление.


Индексация строк в ng-repeat

Protractor позволяет работать с отдельными строками через методы:

  • row(index) — доступ к строке по индексу.
  • column(binding) — доступ к конкретной колонке по биндингу Angular.

Пример:

const secondRow = element(by.repeater('item in items').row(1));
const priceColumn = secondRow.element(by.binding('item.price'));
expect(priceColumn.getText()).toBe('200');

Использование row и column делает тесты более читаемыми и структурированными.


Фильтрация и сортировка внутри ng-repeat

Angular позволяет использовать фильтры и сортировки внутри ng-repeat, например:

<div ng-repeat="item in items | filter:searchText | orderBy:'name'">
  {{item.name}}
</div>

Protractor корректно работает с такими элементами, если указать точную строку repeater, включая фильтры при необходимости. При проверке отсортированных списков важно учитывать порядок элементов:

const items = element.all(by.repeater('item in items | orderBy:\'name\''));
expect(items.first().getText()).toBe('Alpha');

Асинхронные операции с ng-repeat

AngularJS работает с асинхронными данными, и ng-repeat может обновляться после загрузки данных. Для корректного тестирования необходимо использовать ожидания:

const items = element.all(by.repeater('item in items'));
browser.wait(() => items.count().then(count => count > 0), 5000);

expect(items.count()).toBeGreaterThan(0);

Использование browser.wait() гарантирует, что тест не упадет на пустой коллекции до загрузки данных.


Итоговые рекомендации при работе с ng-repeat

  • Всегда использовать точное имя переменной и коллекции из Angular-шаблона.
  • Для доступа к вложенным элементам комбинировать element.all() с element() внутри конкретного элемента.
  • Для проверки данных модели использовать evaluate().
  • Проверять количество элементов через count() перед выполнением операций.
  • При асинхронной загрузке использовать browser.wait() или встроенные ожидания Protractor.

Работа с ng-repeat является базовым, но мощным инструментом для тестирования динамических списков в AngularJS-приложениях. Правильное использование локаторов, методов row, column, evaluate и асинхронных ожиданий обеспечивает надежность и читаемость автоматизированных тестов.