67

I need to test that events get correctly emitted or broadcast, and trigger events manually.

What's the best way to do this?

0

3 Answers 3

120

If you're just needing some testing on event firing and catching, this is how I do it. For ensuring that a certain event gets fired ($emit-ed or $broadcast-ed), a spy is the way to go. You need a reference to the scope that will be calling the $emit or $broadcast, and then just to do something like this:

spyOn(scope, "$emit")
//run code to test
expect(scope.$emit).toHaveBeenCalledWith("MY_EVENT_ID", other, possible, args);

If you don't need or don't want to worry about the arguments that are passed with the $emit, you can put an $on on the $rootScope and set a flag to know the event was emitted. Something like this:

var eventEmitted = false;
$rootScope.$on("MY_EVENT_ID", function() {
   eventEmitted = true;
});
//run code to test
expect(eventEmitted).toBe(true);

For testing functionality that runs when an event is caught ($on), it's a little easier. Just get a $rootScope from the inject function and then send the desired event.

$rootScope.$broadcast("EVENT_TO_TEST", other, possible, args);
//expects for event here

Now, I imagine this event handling would be happening in a directive or a controller (or both) For setting up directive tests, see https://github.com/vojtajina/ng-directive-testing. For setting up controller tests, see https://github.com/angular/angular-phonecat/blob/master/test/unit/controllersSpec.js#L27

Sign up to request clarification or add additional context in comments.

5 Comments

This is good for exact matches but how would one match a subset of arguments? For example if the args are just one object {p1:'yes', p2:'no'} how would you expect that p1:'yes' no matter what p2 is (or if it event exists)? I know there's the 'any' jasmine keyboard but that seems to be the opposite - not fine grained enough control. Any middle ground where you can expect just the args you want?
@LukeMadera Jasmine has jasmine.objectContaining. From the docs: jasmine.objectContaining is for those times when an expectation only cares about certain key/value pairs in the actual object.
Thanks, but would there be a way to use jasmine? Something like: expect(scope.$emit.calls.argsFor(0)[0]).toBe('MY_EVENT_ID');
@dnc253 I have a parent node listening for $emit events. My tests pass only when I use $rootScope.$broadcast and then check for events, they don't pass for $rootScope.$emit, is this because $emit can only traverse up the node and not itself and to the children nodes?
@cameronjroe a bit late, but I believe using toHaveBeenCalledWith is suitable even to just check if an event was fired. This is because the event name is an argument for $emit, so here the test would make sense.
0

Here are the steps you should follow to $broadcast event in angular JS

While inijecting initialize the rootScope and scope stub as given below:

var rootScope;
var scopeStub = beforeEach(function() {
    inject(function($rootScope, _$controller_) {
        rootScope = $rootScope;
        scopeStub = $rootScope.$new();
        $controller = _$controller_;
    });
});

After controller is created raise event using rootScope like below:

rootScope.$broadcast('eventName', parameter1);

Comments

0

We used this sintax for A1

=========== Controller ========
    var vm = this;
    $scope.$on('myEvent', function(event, data){
        console.log('event number', data.id);
    });
============ Test =============
 it('should throw myEvent', function() {
    var data = {};
    $scope.$broadcast('myEvent', {id:1});
    $scope.$broadcast('myEvent', {id:2});
    $scope.$broadcast('myEvent', {id:3});
});

============ Output ============
Chrome LOG: '--------------------------------------------'
Chrome LOG: 'event number', 1
Chrome LOG: 'event number', 2
Chrome LOG: 'event number', 3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.