Что такое Angular и как Protractor его видит

Angular — это фронтенд-фреймворк для построения динамических веб-приложений, основанный на компонентной архитектуре и двухстороннем связывании данных (two-way data binding). Его ключевая особенность — реактивность: изменение данных модели автоматически отражается в пользовательском интерфейсе, а действия пользователя могут мгновенно обновлять состояние приложения. Angular использует Zone.js для отслеживания асинхронных операций, таких как HTTP-запросы, таймеры и события пользовательского интерфейса, что позволяет фреймворку управлять жизненным циклом изменений без вмешательства разработчика.

Для автоматизированного тестирования Angular-приложений важна способность тестового фреймворка понимать внутренние механизмы приложения. Здесь на помощь приходит Protractor.


Как Protractor взаимодействует с Angular

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

1. Автоматическое ожидание (Automatic Waiting)

Protractor использует встроенный механизм Angular-specific wait, который позволяет тесту ждать завершения всех асинхронных операций в Angular перед выполнением действий.

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

  • Protractor отслеживает http * *и * *timeout, гарантируя, что HTTP-запросы и таймеры завершены.
  • Используется Testability API Angular (angular.getTestability), чтобы определить, когда приложение находится в стабильном состоянии.
  • Это устраняет необходимость явного использования browser.sleep() или длинных таймаутов для синхронизации.

2. Поиск элементов в Angular

Protractor расширяет стандартные селекторы WebDriver, добавляя Angular-специфичные локаторы:

  • by.model('modelName') — поиск по привязке модели (ng-model).
  • by.binding('expression') — поиск элементов по Angular-выражениям, отображающим данные ({{expression}}).
  • by.repeater('item in items') — работа с повторяющимися элементами (ng-repeat).
  • by.cssContainingText('css', 'text') — поиск по CSS с фильтрацией по тексту внутри Angular-элемента.

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

3. Angular Zones и синхронизация

Angular использует зоны (Zones) для отслеживания асинхронной активности. Protractor интегрируется с этим механизмом через browser.waitForAngular(), что позволяет:

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

Настройка Protractor для Angular

Чтобы Protractor корректно видел Angular, требуется правильная конфигурация:

  1. Включение Angular-синхронизации По умолчанию Protractor ожидает Angular-приложение. Для не-Angular страниц нужно отключить ожидание:

    browser.waitForAngularEnabled(false);
  2. Использование Testability API Angular 2+ предоставляет getTestability для проверки готовности приложения. Protractor автоматически использует этот API, если приложение корректно интегрировано с Angular.

  3. Конфигурация селекторов Для старых AngularJS-приложений можно использовать by.model, by.binding и by.repeater. Для современных Angular (2+) рекомендуется использовать data-testid атрибуты или стандартные CSS-селекторы вместе с Angular-aware синхронизацией.


Пример взаимодействия с Angular-элементами

// Ожидание, пока приложение станет стабильным
browser.waitForAngular();

// Поиск инпута по модели и ввод данных
let username = element(by.model('user.name'));
username.sendKeys('test_user');

// Проверка данных, привязанных к выражению
let greeting = element(by.binding('user.greeting'));
expect(greeting.getText()).toEqual('Hello, test_user!');

// Работа с повторяющимся списком
let items = element.all(by.repeater('item in items'));
expect(items.count()).toBe(5);

В этом примере видно, как Protractor напрямую взаимодействует с Angular-логикой, а не только с HTML-структурой.


Ограничения и особенности

  • Protractor чувствителен к версии Angular. Старые селекторы (by.model, by.binding) не работают в Angular 2+.
  • Для многостраничных приложений с комбинацией Angular и сторонних библиотек может потребоваться ручная синхронизация (browser.wait или browser.sleep), если Testability API недоступен.
  • Использование Angular-зависимых локаторов повышает связность тестов с кодом приложения, поэтому при рефакторинге моделей и выражений тесты могут ломаться.

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