Michael Hunziker Michael Hunziker - 1 year ago 138
AngularJS Question

Testing window.postMessage directive

I'm having trouble testing my directive which enables cross-document messaging by registering a message handler:

.directive('messaging', function ($window, MyService) {
return {
link: function () {
angular.element($window).on('message', MyService.handleMessage);

All I want to unit test is that when this directive is compiled, and
is called, my message handler should be called:

http://jsfiddle.net/mhu23/L27wqn14/ (including jasmine test)

I'd appreciate your help!

Answer Source

Your are using original window API, you are not mocking it, so the method postMessage will keep it's asynchronous behavior. Knowing that, tests should be written in an asynchronous way. In JSFiddle you have Jasmine 1.3, so test should look kinda like this:

it('should ....', function () {

    var done = false;

    spyOn(MyService,'handleMessage').andCallFake(function () {
        // set the flag, let Jasmine know when callback was called
        done = true; 

    runs(function () {
        // trigger async call

    waitsFor(function () {
        // Jasmine waits until done becomes true i.e. when callback be called
        return done; 

    runs(function () {


Check the docs about testing async with Jasmine 1.3. And here is a working JSFiddle.

It would be a bit easier in Jasmine 2.x:

it('should ....', function (done) {

    spyOn(MyService,'handleMessage').and.callFake(function () {


Also, I have to mention, that you have to change how you add a listener from this

angular.element($window).on('message', MyService.handleMessage);

to that

angular.element($window).on('message', function (e) {

because .on registers a function itself, it won't be used as a method attached to the MyService, so you won't be able to spy on it.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download