I've got a directive that adds a click handler to an element:
module.directive('toggleSection', ['$timeout', function ($timeout) { return { restrict: 'A', link: function (scope, element, attrs) { element.bind('click', function (event) { scope.$apply(function () { var scopeProp = 'show' + attrs.toggleSection; event.preventDefault(); event.stopPropagation(); scope[scopeProp] = !scope[scopeProp]; return false; }); }); } }; }]);
When the element is clicked, it toggles another property on the scope, which another element is bound to with ng-show
. It's working as it should in the app.
I've added the following test for the directive:
(function () { 'use strict'; // get the app module from Angular beforeEach(module('app')); describe('myCtrl', function () { var $scope, $rootScope; beforeEach(inject(function ($controller, _$rootScope_) { $scope = {}; $controller('myCtrl', { $scope: $scope }); $rootScope = _$rootScope_; })); describe('the toggleSection directive', function () { var testElement; beforeEach(function () { testElement = $compile('<a toggle-section="Test" href="#">Collapse section</a>')($rootScope); $rootScope.$digest(); }); it('inverts the value of the specified scope property', function () { $scope.showTest = false; testElement.click(); expect($scope.showTest).toEqual(true); }); }); });
In the real code there are properties like $scope.showSection1 = false
and by adding console logs in the directive I can see the properties before and after clicking the bound element and they have the expected values (e.g. the property starts as false
and after you click the toggle element once it changes to true
).
However, the test always fails with 'Expected false to equal true'. I think it's to do with the $apply
method, because none of the show properties seem to exist on the scope when I run the test.
Other tests I have (even in the same spec file), which don't use the directive can see properties on the scope just fine.
What am I doing wrong?
element = angular.element('<my-directive/>');compile(element)(scope);scope.$digest();
$digest()
being called on$rootScope
), but now the test has an error: 'undefined' is not a function (evaluating 'scope.$apply') - it's tripping up on the use of '$apply()' in the directive itself..?$scope = {}
but$scope = $rootScope.$new();