Вызов функций приложения

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


Использование browser.executeScript и browser.executeAsyncScript

Protractor предоставляет два метода для вызова JavaScript-кода в контексте страницы:

  1. browser.executeScript — выполняет синхронный JavaScript-код и возвращает результат.
  2. browser.executeAsyncScript — выполняет асинхронный JavaScript-код с использованием обратного вызова callback.

Пример синхронного вызова функции:

let result = await browser.executeScript('return window.myApp.calculateSum(2, 3);');
console.log(result); // 5

Пример асинхронного вызова:

let result = await browser.executeAsyncScript(function(a, b, callback) {
    window.myApp.calculateAsync(a, b).then(callback);
}, 4, 5);
console.log(result); // 9

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

  • Аргументы после функции передаются как параметры в неё.
  • Асинхронный вариант нужен, если функция возвращает Promise.
  • Любые изменения в DOM через executeScript немедленно отражаются на странице.

Вызов Angular-функций через ng.probe

Для глубокого взаимодействия с компонентами Angular можно использовать ng.probe, доступный в режиме отладки Angular (включается через debugElement).

Пример получения экземпляра компонента и вызова метода:

let componentInstance = await browser.executeScript(() => {
    const debugEl = ng.probe(document.querySelector('app-root'));
    return debugEl.componentInstance;
});

await browser.executeScript(instance => {
    instance.performAction();
}, componentInstance);

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

  • Поддерживается только в Angular-приложениях с включенной поддержкой ng.probe.
  • Позволяет напрямую обращаться к методам компонентов и изменять их состояние.
  • Полезно для тестирования внутренних механизмов без обхода через UI.

Вызов функций внутри Angular Zone

Angular использует зону (NgZone) для отслеживания изменений и обновления представления. Прямой вызов функций вне зоны может не инициировать обновление данных в интерфейсе. Для корректной работы используют browser.executeScript с NgZone.run:

await browser.executeScript(() => {
    const appRoot = document.querySelector('app-root');
    ng.probe(appRoot).injector.get(ng.coreTokens.NgZone).run(() => {
        ng.probe(appRoot).componentInstance.updateData('new value');
    });
});

Преимущества подхода:

  • Обеспечивает корректное обновление UI после вызова метода.
  • Исключает необходимость ожидания изменений через browser.wait.

Передача аргументов в функции

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

Пример передачи объекта:

let data = { name: 'Test', count: 10 };
await browser.executeScript((obj) => {
    window.myApp.processData(obj);
}, data);

Важно:

  • Ссылки на DOM-элементы из контекста Node.js не работают напрямую.
  • Объекты сериализуются через JSON, поэтому методы внутри объектов не передаются.

Асинхронные функции и ожидание результатов

Если вызываемая функция возвращает Promise, Protractor автоматически ожидает её разрешения в executeAsyncScript. Пример:

let result = await browser.executeAsyncScript((callback) => {
    fetch('/api/data')
        .then(response => response.json())
        .then(data => callback(data));
});
console.log(result);

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

  • Использование await с executeAsyncScript гарантирует, что тест не продолжится до получения результата.
  • Для сложных сценариев можно объединять несколько вызовов и ожиданий через промисы.

Вызов функций для тестирования состояния и бизнес-логики

Прямой вызов функций приложения позволяет:

  • Проверять работу методов без прохождения через UI.
  • Имитировать пользовательские действия, которые сложно воспроизвести через клики и ввод текста.
  • Настраивать данные приложения в нужное состояние для тестов.

Пример подготовки данных:

await browser.executeScript(() => {
    window.myApp.resetDatabase();
    window.myApp.addTestUser({ username: 'user1', role: 'admin' });
});

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

  • Сохранять вызовы функций в отдельных хелперах для повторного использования.
  • Не вызывать методы напрямую из компонента без обдуманного контроля зоны Angular, чтобы избежать рассинхронизации UI.
  • Использовать асинхронные вызовы для работы с API и внутренними сервисами приложения.

Отладка вызовов функций

Protractor позволяет отлаживать скрипты через:

  • browser.pause() — приостанавливает тест и открывает REPL для интерактивного исполнения команд.
  • console.log внутри executeScript — выводит данные в браузерную консоль, что удобно для проверки промежуточных результатов.

Пример:

await browser.executeScript(() => {
    console.log('Current state:', window.myApp.state);
});

Преимущества прямого вызова функций

  1. Ускорение тестов за счет обхода UI.
  2. Возможность тестирования бизнес-логики в изоляции.
  3. Удобство подготовки состояния приложения для интеграционных тестов.
  4. Точный контроль над асинхронными процессами Angular.