Отключение Angular синхронизации

Protractor изначально разработан для тестирования Angular-приложений и использует встроенный механизм ожидания завершения всех асинхронных операций Angular перед выполнением действий с элементами страницы. Это поведение обеспечивает стабильность тестов для Angular-приложений, но иногда необходимо отключить автоматическую синхронизацию, особенно при тестировании страниц, не относящихся к Angular, или при смешанных приложениях, где часть страниц написана на Angular, а часть — на обычном HTML/JS.


Механизм синхронизации Angular

Protractor работает поверх WebDriverJS и реализует ожидание Angular-зоны (ngZone) перед взаимодействием с элементами. Он проверяет:

  • наличие завершенных HTTP-запросов через $http и $timeout,
  • завершение всех событий Angular,
  • стабилизацию всех асинхронных операций Angular.

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


Когда требуется отключение синхронизации

Отключение автоматической синхронизации Angular необходимо в следующих случаях:

  1. Тестирование не-Angular страниц Protractor при работе с обычными HTML-страницами будет ждать стабилизации Angular, которая отсутствует, что приведет к зависанию теста.

  2. Смешанные приложения Если часть приложения использует Angular, а часть — нет, требуется временно отключать синхронизацию при переходе на не-Angular страницы.

  3. Необычные Angular конфигурации Некоторые сторонние библиотеки или кастомные зоны Angular могут нарушить стандартный механизм ожидания.


Отключение синхронизации через browser.waitForAngularEnabled

Для управления синхронизацией используется метод browser.waitForAngularEnabled().

// Отключение синхронизации
await browser.waitForAngularEnabled(false);

// Переход на не-Angular страницу
await browser.get('https://example.com/non-angular');

// Выполнение действий на странице
const button = element(by.id('submit'));
await button.click();

// Включение синхронизации для следующей Angular страницы
await browser.waitForAngularEnabled(true);

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

  • true — синхронизация включена (по умолчанию).
  • false — синхронизация отключена.
  • Метод применяется глобально для текущей сессии браузера, но его можно вызывать перед каждым переходом на страницу, чтобы управлять состоянием синхронизации.

Использование browser.ignoreSynchronization (устаревший подход)

Ранее для отключения синхронизации использовалось свойство browser.ignoreSynchronization:

browser.ignoreSynchronization = true;

Однако начиная с Protractor 5.x рекомендуется использовать browser.waitForAngularEnabled, так как оно:

  • поддерживает асинхронные вызовы (await browser.waitForAngularEnabled(false)),
  • более явно управляет состоянием синхронизации.

Практические сценарии

  1. Тестирование формы на не-Angular странице:
await browser.waitForAngularEnabled(false);
await browser.get('https://example.com/form');
await element(by.css('input[name="email"]')).sendKeys('test@example.com');
await element(by.css('button[type="submit"]')).click();
  1. Смешанное приложение:
// Angular страница
await browser.get('https://example.com/angular-page');

// Выполнение действий на Angular странице
await element(by.model('user.name')).sendKeys('John');

// Переход на не-Angular страницу
await browser.waitForAngularEnabled(false);
await browser.get('https://example.com/static-page');
await element(by.css('#download')).click();

// Возврат на Angular страницу
await browser.waitForAngularEnabled(true);
await browser.get('https://example.com/angular-page');
  1. Автоматизация тестов с переключением контекста:
describe('Микс Angular и не-Angular страниц', function() {

    it('Выполняет действия на Angular странице', async function() {
        await browser.get('https://example.com/angular');
        await element(by.binding('user.name')).getText();
    });

    it('Выполняет действия на не-Angular странице', async function() {
        await browser.waitForAngularEnabled(false);
        await browser.get('https://example.com/static');
        await element(by.css('#static-button')).click();
    });

});

Особенности взаимодействия с элементами при отключенной синхронизации

  • Без синхронизации необходимо явно ожидать появление элементов через ExpectedConditions или browser.wait, иначе возможны ошибки типа element not visible или stale element reference.

Пример явного ожидания:

const EC = protractor.ExpectedConditions;
const button = element(by.id('submit'));

await browser.wait(EC.elementToBeClickable(button), 5000);
await button.click();
  • При отключенной синхронизации Protractor не будет автоматически ждать завершения $http или $timeout, поэтому асинхронные операции на Angular-странице могут быть недоступны для взаимодействия до явного ожидания.

Рекомендации по использованию

  1. Всегда возвращать синхронизацию к состоянию true после работы с не-Angular страницами.
  2. Для тестирования Angular-приложений не отключать синхронизацию без крайней необходимости.
  3. Комбинировать waitForAngularEnabled(false) с явными ожиданиями ExpectedConditions, чтобы избежать нестабильности тестов.
  4. Использовать этот подход при интеграции с сторонними страницами или сервисами, которые не управляются Angular.

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