Reputation: 6432
I am attempting to trigger the $scope.$on()
method in a controller that is fired when I $rootScope.broadcast()
an event. I found this question useful: How can I test events in angular?, but I'm still having trouble detecting an event being broadcast from the $rootScope
up through a controller's $scope
.
So far I've managed to test that the $broadcast
method is called on a corresponding $rootScope
, but not that the $on
method was called on a corresponding $scope
when $broadcast
is called on the $rootScope
.
I attempted to $rootScope.$broadcast
directly in my test, but my spy is not picking up on the event.
This is my controller:
angular.module('app.admin.controllers.notes', [])
.controller('NotesCtrl', function($scope) {
$scope.$on('resource-loaded', function(event, resource) { // I want to test this
$scope.parentType = resource.type;
$scope.parentId = resource.id;
});
});
This is my test:
describe('The notes controller', function() {
beforeEach(module('app.admin.controllers.notes'));
var scope, rootScope, NotesCtrl;
beforeEach(inject(function($controller, $injector, $rootScope) {
rootScope = $rootScope;
scope = $rootScope.$new(); // I've tried this with and without $new()
NotesCtrl = $controller('NotesCtrl', {$scope: scope}); // I've tried explicitly defining $rootScope here
}));
it('should respond to the `resource-loaded` event', function() {
spyOn(scope, '$on');
rootScope.$broadcast('resource-loaded'); // This is what I expect to trigger the `$on` method
expect(scope.$on).toHaveBeenCalled();
});
});
And here's the plunkr. I've included a passing test of the $broadcast
method for reference, mainly because I setup the tests in the same manner.
I've read quite a few questions relating to testing events in AngularJS, and it always seems to be a scoping issue. I've heard that in Karma unit testing, $rootScope
and $scope
are the same thing, but I'm not really sure what the implication is. I've tried defining the $rootScope
and the $scope
as the same object, as well as explicitly injecting the $rootScope
into the NotesCtrl
during testing, but nothing makes my test go green.
How can I get the $on
method in my NotesCtrl
to fire for this test?
Upvotes: 6
Views: 9099
Reputation: 31
@kirill.buga
Using $broadcast is right, not $emit because :
https://docs.angularjs.org/api/ng/type/$rootScope.Scope Dispatches an event name upwards through the scope hierarchy notifying the registered $rootScope.Scope listeners.
Problem of @ben-harold is trying to spy $on instead of the result of code in the $on.
Upvotes: 1
Reputation: 1159
Try to use
$rootScope.$emit('resource-loaded');
Works fine in my tests.
Upvotes: 1
Reputation: 692181
What makes it not working is the fact that you're spying the $on
function. It works fine when not sying it: http://plnkr.co/edit/hNEj7MmDDKJcJ7b298OB?p=info. And the reason is actually simple. When an event is brodcasted, what is called is not the $on()
function. What is called is the callback function passed as argument to $on()
previously: the listener.
Note that, by spying the $on function, you're not testing your code here. All you're trying to test is that when broadcasting en event, child scopes receive it. So you're testing AngularJS itself.
Upvotes: 12