2015-06-11 7 views
8

Я пытаюсь использовать Jasmine 2.0 для написания модульных тестов для некоторой логики в приложении AngularJS, но логика находится внутри прослушивателя событий. От контроллера:Тестирование postMessage с Jasmine async не работает

window.addEventListener('message', function(e) { 
    if (e.data === "sendMessage()") { 
     $scope.submit(); 
    } 
    }, false); 

А из тестового файла:

describe("post message", function() { 
    beforeEach(function(done) { 
     var controller = createController(controllerParams); 
     spyOn($scope, 'submit'); 
     window.postMessage('sendMessage()', '*'); 
     done(); 
    }); 

    it('should submit on a sent message', function (done) { 
     expect($scope.submit).toHaveBeenCalled(); 
     done(); 
    }); 
    }); 

Но тест не пройден, шпион никогда не быть пораженным. Дополнительная информация от ввода в консоль отладочной информации:

  • window.addEventListener в контроллере IS получает вызов.
  • Блок beforeEach и it оба вызываются.
  • Вышеупомянутый обработчик сообщений в контроллере не вызывается во время теста.
  • Сообщение, отправленное в этом тесте, в конечном итоге получает обработчик сообщения несколько раз, но только после завершения теста.

Что, по моему мнению, отсутствует здесь?

+0

Вы не должны вызывать postMessage в * другом * окне, чем тот, который получит событие? (скажем, создание всплывающего окна, как это делается на https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage?redirectlocale=en-US&redirectslug=DOM%2Fwindow.postMessage) – phtrivier

+0

Пробное изменение это сообщение после всплывающего окна, а не постсообщение из окна, но все, что изменилось, заключается в том, что вместо того, чтобы получать сообщение слишком поздно, оно вообще не получает сообщение. –

+0

@AlanGordon: Вы уже нашли решение для этого? У меня такие же проблемы ;-) –

ответ

6

Это происходит потому, что в вашем beforeEach блоке вы звоните window.postMessage() (который является асинхронным, и вы не знаете, когда он собирается выполнить), а затем вы звоните done() сразу после него, как это будет синхронный код. Но window.postMessage() async, и в основном вам нужно позвонить done(), когда ваша операция async завершена. Это можно сделать так:

beforeEach(function(done) { 
    spyOn(someObject, 'submit').and.callFake(function() { 
     done(); 
    }); 
}); 

Так что, когда ваш шпион выполняет, то операция async считается завершенной.

Это может быть выражено еще короче:

beforeEach(function(done) { 
    spyOn(someObject, 'submit').and.callFake(done); 
}); 

Вот полный код:

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(); 
    }); 

}); 

Смотреть рабочий JS Bin: http://jsbin.com/xikewogagu/1/edit?html,js,console,output

Я не использовал Угловое в этом образце потому что он воспроизводится с чистым JS.

+0

Это было именно это! Спасибо за помощь. –

Смежные вопросы