Представить объект из приложения Angularjs для теста Protractor

Я пишу сквозные тесты для своего приложения на основе AngularJS, используя Protractor. В некоторых случаях для тестирования требуется использование макетов — например, проблема с сетевым подключением. Если запрос AJAX к серверу завершается неудачно, пользователь должен увидеть предупреждающее сообщение.

Мои моки прописаны в приложении как сервисы. Я хочу, чтобы они были доступны для тестов, чтобы написать что-то вроде этого:

var proxy;
beforeEach(function() { proxy = getProxyMock(); });

it("When network is OK, request succeeds", function(done) {
    proxy.networkAvailable = true;

    element(by.id('loginButton')).click().then(function() {
        expect(element(by.id('error')).count()).toEqual(0);
        done();
    });
});

it("When network is faulty, message is displayed", function(done) {
    proxy.networkAvailable = false;

    element(by.id('loginButton')).click().then(function() {
        expect(element(by.id('error')).count()).toEqual(1);
        done();
    });
});

Как реализовать функцию getProxyMock для передачи объекта из приложения в тест? Я могу хранить прокси в объекте window приложения, но до сих пор не знаю, как получить к нему доступ.


person Impworks    schedule 07.12.2015    source источник


Ответы (1)


После некоторого чтения и понимания процесса тестирования это оказалось невозможным. Тесты выполняются в NodeJS, а внешний код — в браузере — экземпляры объектов Javascript не могут быть по-настоящему разделены между двумя разными процессами.

Однако есть обходной путь: вы можете запустить скрипт внутри браузера.

Во-первых, ваш интерфейсный код должен предоставлять своего рода локатор сервисов, например:

angular.module('myModule', [])
       .service('proxy', NetworkProxy)
       .run(function(proxy) {
           window.MY_SERVICES = {
               proxy: proxy,
           };
       });

Затем тест проходит так:

it("Testing the script", function(done) {
    browser.executeScript(function() {
        window.MY_SERVICES.proxy.networkAvailable = false;
    });

    element(by.id('loginButton')).click().then(function() {
        expect(element.all(by.id('error')).count()).toEqual(1);
        done();
    });
});

Обратите внимание, что при использовании executeScript функция сериализуется для отправки в браузер для выполнения. Это накладывает некоторые ограничения, о которых стоит помнить: если ваша функция скрипта возвращает значение, это клон исходного объекта из браузера. Обновление возвращаемого значения не изменит оригинал! По той же причине нельзя использовать замыкания в функции.

person Impworks    schedule 08.12.2015