I am trying to unit test a directive with a two-way bound property (=). The directive works in my app, but I can't get a unit test working that tests the two-way binding.
I have been trying to get this working for days. I've read MANY examples that use some but not all of the features I want to use: controllerAs, bindToController & isolateScope(). (Forget about templateURL, which I also need. I will add that if I can get this working! :)
I'm hoping someone can tell me how to show a change in the parent scope reflected in the isolate scope.
Here is a plunkr that contains the code below:
http://plnkr.co/edit/JQl9fB5kTt1CPtZymwhI
Here is my test app:
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
};
}
);
And here is the spec:
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);
});
});
You have to correct the way you're testing your directive. You're directly changing
isolatedScopeof an object and thereafter verifying thectrlobject which unrelatedDOMwhich you had compiled.Basically what you should be doing is as soon as you compiled a DOM with scope (here it is
<greeting-directive testprop="testprop"></greeting-directive>). So that scope will hold the context of compiled do. In short you can playtestpropproperty value. or same thing will be available insideelement.scope(). As soon as you change any value inscope/currentScope. You can see the value gets updated inside directiveisolatedScope. One more thing I'd like to mention is when you docontrollerAswithbindToController: true, angular adds property with controller alias insidescopethat's we verifiedisolatedScope.greetingController.testpropinsideassertCode
Demo Plunker