Тестовый модуль angularjs не пройден с controllerAs, bindToController & isolateScope()

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

Я пытался заставить это работать в течение нескольких дней. Я прочитал МНОГО примеров, которые используют некоторые, но не все функции, которые я хочу использовать: controllerAs, bindToController & isolateScope(). (Забудьте о templateURL, который мне также нужен. Я добавлю это, если я смогу заставить это работать!:)

Я надеюсь, что кто-то может сказать мне, как показать изменение родительской области, отраженной в области изоляции.

Вот plunkr, который содержит код ниже:

http://plnkr.co/edit/JQl9fB5kTt1CPtZymwhI

Вот мое тестовое приложение:

var app = angular.module('myApp', []);

angular.module('myApp').controller('greetingController', greetingController);
greetingController.$inject = ['$scope'];
function greetingController($scope) {
  // this controller intentionally left blank (for testing purposes)
}

angular.module('myApp').directive('greetingDirective',
        function () {
            return {
                scope: {testprop: '='},
                restrict: 'E',
                template: '<div>Greetings!</div>',
                controller: 'greetingController',
                controllerAs: 'greetingController',
                bindToController: true
            };
        }
);

А вот и спецификация:

describe('greetingController', function () {

var ctrl, scope, rootScope, controller, data, template,
        compile, isolatedScope, element;

beforeEach(module('myApp'));

beforeEach(inject(function ($injector) {

    rootScope = $injector.get('$rootScope');
    scope = rootScope.$new();
    controller = $injector.get('$controller');
    compile = $injector.get('$compile');

    data = {
        testprop: 1
    };

    ctrl = controller('greetingController', {$scope: scope}, data);
    element = angular.element('<greeting-directive testprop="testprop"></greeting-directive>');
    template = compile(element)(scope);
    scope.$digest();
    isolatedScope = element.isolateScope();

}));

// PASSES
it('testprop inital value should be 1', function () {
    expect(ctrl.testprop).toBe(1);
});

// FAILS: why doesn't changing this isolateScope value 
// also change the controller value for this two-way bound property?
it('testprop changed value should be 2', function () {
    isolatedScope.testprop = 2;
    expect(ctrl.testprop).toBe(2);
}); 
});

1 ответ

Решение

Вы должны исправить то, как вы проверяете свою директиву. Вы напрямую меняете isolatedScope объекта и после этого проверка ctrl объект, который не связан DOM который вы составили.

В основном, что вы должны делать, это как только вы скомпилировали DOM с областью видимости (здесь это <greeting-directive testprop="testprop"></greeting-directive>). Так что эта область будет содержать контекст скомпилированного do. Короче можно поиграть testprop стоимость имущества. или то же самое будет доступно внутри element.scope(), Как только вы измените любое значение в scope/currentScope, Вы можете видеть, что значение обновляется внутри директивы isolatedScope, Еще одна вещь, которую я хотел бы отметить, когда вы делаете controllerAs с bindToController: true, angular добавляет свойство с псевдонимом контроллера внутри scope это мы убедились isolatedScope.greetingController.testprop внутри assert

Код

describe('greetingController', function() {

  var ctrl, scope, rootScope, controller, data, template,
    compile, isolatedScope, currentScope, element;

  beforeEach(module('myApp'));

  beforeEach(inject(function($injector) {

    rootScope = $injector.get('$rootScope');
    scope = rootScope.$new();
    controller = $injector.get('$controller');
    compile = $injector.get('$compile');

    data = { testprop: 1 };

    ctrl = controller('greetingController', { $scope: scope }, data);
    element = angular.element('<greeting-directive testprop="testprop"></greeting-directive>');
    template = compile(element)(scope);
    scope.$digest();
    currentScope = element.scope();
    //OR
    //currentScope = scope; //both are same
    isolatedScope = element.isolateScope();
  }));

  // First test passes -- commented

  it('testprop changed value should be 2', function() {
    currentScope.testprop = 2; //change current element (outer) scope value
    currentScope.$digest(); //running digest cycle to make binding effects
    //assert
    expect(isolatedScope.greetingController.testprop).toBe(2);
  });

});

Демо Плункер

Другие вопросы по тегам