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); }); 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); }); 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); }); 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
Post a Comment