Reputation: 961
The gist of my issue is that I don't think I am correctly accessing the scope and controller of my directive in accompanying unit tests.
I have a directive that looks something like this:
app.controller('GalleryDirectiveController', ['$scope', '$element', '$timeout', function($scope, $element, $timeout){
$scope.panels = [];
this.addPanel = function(panel){
// Timeout to help with $scope.$watch in other directives
return $timeout(function(){ $scope.panels.push(panel); }, 0);
};
}]);
app.directive('gallery', function(){
return {
restrict: 'E',
controller: 'GalleryDirectiveController'
};
});
What I am trying to do now is write unit tests that mock a collection of gallery panels that add themselves to the gallery. Unfortunately, I don't think I am correctly accessing the controller and scope of the directives in my unit tests, so they never pass.
The unit test looks something like this:
describe('app Gallery', function(){
var gallery;
var $scope;
beforeEach(module('app'));
beforeEach(inject(function($compile, $rootScope){
var element = angular.element('<gallery/>');
$compile(element)($rootScope.$new());
$rootScope.$digest();
$scope = element.isolateScope() || element.scope();
gallery = element.controller('gallery');
}));
it('should add panels to the gallery', function(){
for (var i = 0; i < 9; i++) {
gallery.addPanel({
$el : $('<div></div>')
});
}
// Each panel is added in a timeout, so I thought
// the problem might have been a timing issue
waitsFor(function(){
return $scope.panels.length !== 0;
}, 'the panels to be added', 200);
});
});
$scope.panels.length is always zero. This makes me think that the $scope variable I am setting in my unit test is not the same $scope being modified by the controller. For what it's worth, other unit tests that check if gallery.addPanel and $scope.panels are defined pass as expected.
Hopefully I am just missing something small. My fear is that I may have created a hard-to-test gallery directive.
Upvotes: 0
Views: 378
Reputation: 123739
You can flush the $timeout
before setting your expectation.
i.e:-
var $timeout; //or var flushTimeout;
...
beforeEach(inject(function($compile, $rootScope, _$timeout_){ //<-- inject timeout
$timeout = _$timeout_; //Save it in outer scope
//or flushTimeout = _$timeout_.flush
...
and in your test do:-
it('should add panels to the gallery', function(){
for (var i = 0; i < 9; i++) {
gallery.addPanel({
$el : $('<div></div>')
});
}
$timeout.flush(); //or flushTimeout();
expect($scope.panels.length).toEqual(9);
});
Upvotes: 1