Angular приложения

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

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

Особенности работы Angular с WebDriverIO

Angular использует зоны (zones) для отслеживания изменений, которые происходят в приложении. Это означает, что после выполнения асинхронной операции, такой как загрузка данных или изменение состояния, приложение может обновить DOM без явного уведомления браузера о завершении работы. В стандартных случаях WebDriverIO не будет знать, что приложение изменилось, если не будет явно указано ожидание завершения асинхронной операции.

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

Настройка WebDriverIO для работы с Angular

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

Пример настройки:

// в wdio.conf.js
exports.config = {
  services: ['webdriver', 'angular'],
  capabilities: [
    {
      browserName: 'chrome',
      'goog:chromeOptions': {
        args: ['--headless', '--disable-gpu', '--window-size=1920x1080']
      }
    }
  ],
  // другие параметры конфигурации
};

После установки и настройки плагина WebDriverIO автоматически подстраивает тесты под особенности работы Angular-приложений.

Ожидание завершения асинхронных операций

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

Основной метод для синхронизации с Angular-приложением — это использование команды waitForAngular или ожидание окончания выполнения всех асинхронных операций:

it('должен дождаться завершения загрузки данных', async () => {
  await browser.waitUntil(
    async () => await browser.executeAsync(() => {
      return new Promise(resolve => {
        if (window.getAllAngularTestabilities().every(testability => testability.isStable())) {
          resolve(true);
        } else {
          resolve(false);
        }
      });
    }),
    {
      timeout: 5000,
      timeoutMsg: 'Angular-приложение не стабилизировалось вовремя'
    }
  );
});

Этот метод проверяет, завершены ли все асинхронные операции в Angular-приложении, прежде чем продолжить тест. Время ожидания можно настроить в параметре timeout.

Взаимодействие с элементами Angular

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

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

При поиске элементов в Angular-приложении важно учитывать, что они могут изменяться в процессе работы приложения. WebDriverIO предоставляет методы для поиска элементов, учитывающие состояние приложения, например:

const button = await $('button[ng-click="submitForm()"]');

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

const button = await $('button[ng-click="submitForm()"]');
await button.waitForDisplayed({ timeout: 5000 });

Этот подход позволяет удостовериться, что элемент появился на странице и доступен для взаимодействия.

Динамические данные

Angular-приложения часто загружают данные с сервера и обновляют DOM на лету. Чтобы дождаться отображения новых данных, можно использовать стратегию ожидания:

const message = await $('#message');
await message.waitUntil(async () => {
  const text = await message.getText();
  return text.includes('Загрузка завершена');
}, {
  timeout: 10000,
  timeoutMsg: 'Сообщение не появилось вовремя'
});

Этот код будет ожидать, пока элемент с id #message не получит текст “Загрузка завершена”, что свидетельствует о завершении асинхронной операции.

Тестирование форм в Angular-приложениях

Angular активно использует двустороннюю привязку данных (two-way data binding) для работы с формами. Это требует особого подхода при тестировании, поскольку состояние формы может быть обновлено асинхронно. WebDriverIO позволяет взаимодействовать с такими элементами, как обычные формы, но с учетом особенностей Angular.

Пример теста для формы:

it('должен корректно отправлять форму', async () => {
  const inputField = await $('#inputField');
  await inputField.setValue('Test value');
  
  const submitButton = await $('button[type="submit"]');
  await submitButton.click();
  
  const successMessage = await $('#successMessage');
  await successMessage.waitForDisplayed();
  expect(await successMessage.getText()).toBe('Форма успешно отправлена');
});

Этот пример проверяет корректную работу формы с динамическим взаимодействием, ожидая появления сообщения об успешной отправке.

Управление состоянием приложения

Angular-приложения могут иметь различные состояния, которые зависят от данных или взаимодействий пользователя. Управление этими состояниями во время тестирования — важная часть процесса.

WebDriverIO позволяет манипулировать состоянием приложения, например, через работу с cookies, локальным хранилищем или сессиями:

it('должен изменять состояние приложения через localStorage', async () => {
  await browser.execute(() => {
    localStorage.setItem('user', JSON.stringify({ id: 123, name: 'Test User' }));
  });

  const userData = await browser.execute(() => {
    return JSON.parse(localStorage.getItem('user'));
  });

  expect(userData.name).toBe('Test User');
});

Использование Angular Testing API

Для более сложных сценариев тестирования можно использовать Angular Testing API в связке с WebDriverIO. Этот подход позволяет не только тестировать пользовательский интерфейс, но и проверять внутренние механизмы работы приложения, такие как сервисы и компоненты.

WebDriverIO позволяет взаимодействовать с Angular-приложением на более глубоком уровне, например, через взаимодействие с внутренними компонентами и сервисами:

await browser.execute(() => {
  const injector = window.ng.getInjector(window.ng.rootComponents[0]);
  const myService = injector.get(MyService);
  return myService.getData();
});

Этот пример показывает, как можно получить доступ к сервисам Angular и проверять их данные напрямую.

Заключение

Тестирование Angular-приложений с использованием WebDriverIO требует учета множества факторов, таких как асинхронные операции, динамическая привязка данных и сложная структура компонентов. Однако с правильной настройкой и использованием специфичных методов синхронизации, таких как waitForAngular, можно успешно автоматизировать тестирование этих приложений.