Say I have the following Backbone Router:
class App.Routers.ThingsRouter extends Backbone.Router
initialize: -> new App.Collections.ThingsCollection()
index: ->
that = this
@collection.fetch success: ->
view = new App.Views.ThingsIndex(collection: that.collection)
$('#app-container').html(view.render().el)
I need to write a Jasmine spy that can watch this and ensure that App.Views.ThingsIndex()
is called. However, as it's AJAX, the following won't work:
describe 'index', ->
@router = new App.Routers.ThingsRouter()
spyOn(@router.collection, 'fetch')
fake = { render: -> '' }
@previewsIndexStub = spyOn(Periscope.Views, 'PreviewsIndex').andReturn(fake)
@router.index()
expect(@previewsIndexStub).toHaveBeenCalled()
Because Jasmine runs the expectation function before the AJAX call can complete. Is there a good way to test a callback like this?
Use jasmines built in waitsFor & runs method in order to wait for the ajax call to complete before executing your expect function. See Jasmine - Asynchronous specs for documentation on these two functions.
describe 'index', ->
@router = new App.Routers.ThingsRouter()
spyOn(@router.collection, 'fetch')
fake = {}; fake.render = -> '';
@previewsIndexStub = spyOn(Periscope.Views, 'PreviewsIndex').andReturn(fake)
@router.index()
waitsFor => @previewsIndexStub.wasCalled
###
Or if you want to wait for the method to be called more than once
use form waitsFor => @previewsIndexStub.callCount > 1
###
runs => expect(@previewsIndexStub).toHaveBeenCalled()
@previewsIndexStub
doesn't have thetoHaveBeenCalled()
function available to it likeexpect(@previewsIndexStub)
does. I get'undefined' is not a function
clem 2012-04-05 19:48