angularjs - Testing directives that require controllers -


so did see question: how mock required directive controller in directive ut problem seems answer thread "change design." wanted make sure there no way this. have directive declares controller used children directives. trying write jasmine tests children directive cant them compile in tests because dependent on controller. here looks like:

addressmodule.directive('address', ['$http', function($http){         return {             replace: false,             restrict: 'a',             scope: {                 config: '='             },             template:   '<div id="addresscontainer">' +                             '<div ng-if="!showaddressselectionpage" basic-address config="config"/>' +                             '<div ng-if="showaddressselectionpage" address-selector addresses="standardizedaddresses"/>' +                         '</div>',             controller: function($scope)             {                 this.showaddressinput = function(){                     $scope.showaddressselectionpage = false;                 };                  this.showaddressselection = function(){                     $scope.getstandardizedaddresses();                 };                  this.finish = function(){                     $scope.finishaddress();                 };             },             link: function(scope, element, attrs) {               ...             }        } }]) 

child directive:

addressmodule.directive('basicaddress360', ['translationservice', function(translationservice){         return {             replace: true,             restrict: 'a',             scope: {                 config: '='             },             template:                 '...',             require: "^address360",             link: function(scope, element, attrs, addresscontroller){             ...             }        } }]) 

jasmine test:

it("should something", inject(function($compile, $rootscope){             parenthtml = '<div address/>';             subdirectivehtml = '<div basic-address>';              parentelement = $compile(parenthtml)(rootscope);             parentscope = parentelement.scope();             directiveelement = $compile(subdirectivehtml)(parentscope);             directivescope = directiveelement.scope();             $rootscope.$digest(); })); 

is there no way me test sub directive jasmine , if so, missing? if test directive without controller functions happy.

i can think of 2 approaches:

1) use both directives

let's assume have following directives:

app.directive('foo', function() {   return {     restrict: 'e',     controller: function($scope) {       this.add = function(x, y) {         return x + y;       }     }   }; });  app.directive('bar', function() {   return {     restrict: 'e',     require: '^foo',     link: function(scope, element, attrs, foo) {       scope.callfoo = function(x, y) {         scope.sum = foo.add(x, y);       }     }   }; }); 

in order test callfoo method, can compile both directives , let bar use foo's implementation:

it('ensures callfoo whatever supposed to', function() {   // arrange   var element = $compile('<foo><bar></bar></foo>')($scope);   var barscope = element.find('bar').scope();    // act   barscope.callfoo(1, 2);    // assert   expect(barscope.sum).tobe(3); });     

working plunker.

2) mock foo's controller out

this 1 not quite straightforward , little tricky. use element.controller() controller of element, , mock out jasmine:

it('ensures callfoo whatever supposed to', function() {     // arrange     var element = $compile('<foo><bar></bar></foo>')($scope);     var foocontroller = element.controller('foo');     var barscope = element.find('bar').scope();     spyon(foocontroller, 'add').andreturn(3);      // act     barscope.callfoo(1, 2);      // assert     expect(barscope.sum).tobe(3);     expect(foocontroller.add).tohavebeencalledwith(1, 2);   }); 

working plunker.

the tricky part comes when 1 directive uses other's controller right away in link function:

app.directive('bar', function() {   return {     restrict: 'e',     require: '^foo',     link: function(scope, element, attrs, foo) {       scope.sum = foo.add(parseint(attrs.x), parseint(attrs.y));     }   }; }); 

in case need compile each directive individually can mock first 1 out before second 1 uses it:

it('ensures callfoo whatever supposed to', function() {   // arrange   var fooelement = $compile('<foo></foo>')($scope);   var foocontroller = fooelement.controller('foo');   spyon(foocontroller, 'add').andreturn(3);    var barelement = angular.element('<bar x="1" y="2"></bar>')   fooelement.append(barelement);    // act   barelement = $compile(barelement)($scope);   var barscope = barelement.scope();    // assert   expect(barscope.sum).tobe(3);   expect(foocontroller.add).tohavebeencalledwith(1, 2); }); 

working plunker.

the first approach way easier second one, relies on implementation of first directive, i.e, you're not unit testing things. on other hand, although mocking directive's controller isn't easy, gives more control on test , removes dependency on first directive. so, choose wisely. :)

finally, i'm not aware of easier way of above. if knows of better approach, please improve answer.


Comments

Popular posts from this blog

c++ - CryptStringToBinary API behavior -

c++ - Correct method for redrawing a layered window -

java.util.scanner - How to read and add only numbers to array from a text file -