We no longer use jQuery and CoffeeScript
Here is a Javascript function reloadUsers()
that fetches a HTML snippet from the server using AJAX and replaces the current .users
container in the DOM:
window.reloadUsers = ->
$.get('/users').then (html) ->
$('.users').html(html)
Testing this simple function poses a number of challenges:
<div class="users">...</div>
container in the current DOM. Obviously the Jasmine spec runner has no such container./users
and we want to prevent network interaction in our unit test.Here is a test that does all that:
describe 'reloadUsers', ->
it 'replaces the user list with a fresh copy from /users', (done) ->
# Mock network connections
jasmine.Ajax.install()
# Create the DOM elements the code works on
affix('.users').text('old is')
reloadUsers().then ->
# Observe the result of the function
expect('.users').toHaveText('new users')
# Tell Jasmine that the example is over
done()
# Fetch the last AJAX request for inspection
request = jasmine.Ajax.requests.mostRecent()
expect(request.url).toMatch(/\/users$/)
expect(request.method).toBe('GET')
# Fake the response
request.respondWith
status: 200
contentType: 'text/html'
responseText: 'new users'
Some notes:
<div class="users">...</div>
containers for the code to work on. We're using
jasmine-fixture
Show archive.org snapshot
to quickly create such a container from a CSS selector by saying affix('.users')
. jasmine-fixture will append the container to the document body and clean it up after the test.done
from the it
block. We are calling done()
once the response has been received and observed by the test.jasmine.Ajax.requests.mostRecent()
returns the most recent AJAX request, which we can inspect for its parameters and payload. We can also trigger a fake response by calling request.respondWith(...)
.haveText(...)
.See Jasmine: Mocking API requests in an Angular service spec on how to do similar things in an Angular application.