This is because in your beforeEach block beforeEach you call window.postMessage() (which is asynchronous, and you don't know when it will be executed), and then you call done() right after it, since it will be synchronous code. But window.postMessage() like async, and basically you need to call done() when your async operation is complete. This can be done as follows:
beforeEach(function(done) { spyOn(someObject, 'submit').and.callFake(function () { done(); }); });
So, when your spy is running, the async operation is considered complete.
This can be expressed even shorter:
beforeEach(function(done) { spyOn(someObject, 'submit').and.callFake(done); });
Here is the complete code:
var someObject = { submit: function () { console.log('Submit'); } }; window.addEventListener('message', function(e) { if (e.data === "sendMessage()") { someObject.submit(); } }, false); // Test describe('window.postMessage', function () { beforeEach(function(done) { spyOn(someObject, 'submit').and.callFake(function () { done(); }); window.postMessage('sendMessage()', '*'); }); it('should submit on a sent message', function () { expect(someObject.submit).toHaveBeenCalled(); }); });
See working js bit: http://jsbin.com/xikewogagu/1/edit?html,js,console,output
I did not use Angular in this example because it plays with pure JS.
Michael radionov
source share