Please note that I'm not maintaining this project anymore. I mostly use Mocha for testing and $.mockjax for faking ajax.
Fake Ajax to be used with the Jasmine BDD framework and jQuery Ajax
Usage in a nutshell: you provide a context which is a list of fake Ajax options with a suitable callback rule (e.g. success or error). When the spec is run, fake ajax is called and the data you have supplied will be passed to the real system under test. You may use a combination of multiple fields for matching fake vs. real options.
You may use the real jQuery.ajax
anytime by calling the global
convenience function realAjax({url: '/example', ...})
.
See spec/fake-ajax-spec.js
for executable specification and many examples.
- Simple and convenient way of faking jQuery Ajax calls in Jasmine spec
- Support for REST requests
- Complete control on what is sent to callback functions
- Support for inspecting Ajax requests (i.e. what is sent to the server) through
latestAjax
andlatestAjaxWithUrlMatching
- Dynamic way for resolving matching Ajax requests: you only need to define
url
if there are no conflicting requests or you may define additional fields such astype
ordataType
- Support for multiple Ajax calls (when e.g. clicking a link), you may have different callback rules for each request
- Function or array of functions (success/error) callbacks (equivalent in jQuery)
- Registering single/multiple fake Ajax callback rules through
registerFakeAjax({...})
fakeAjax({registrations: {...}})
- Support for inlining the fake data (e.g. json, xml or html) or loading the fake data from external files using
loadTestData
, works nicely with jasmine-jquery as long as you useloadTestData
and not equivalent fixture loading functions in jasmine-jquery - All ajax calls are faked by default but you can delegate any ajax call to real ajax by using
.useRealAjaxFor(options)
, e.g.useRealAjaxFor({url: '/example', type: 'post'})
- Real jQuery Ajax can be used anytime through
realAjax
global convenience function - Descriptive and helpful warning/error messages logged to console
- Works nicely with Firefox and Chrome
- jQuery Ajax specific, no plans for supporting other libs (you might want to check out jasmine-ajax if you are not using jQuery)
describe('simple example', function() {
it('just works', function() {
var message = 'Hello '
registerFakeAjax({url: '/simple', successData: 'World!'})
$.get('/simple?foo=bar', function(data) {
message += data
})
expect(message).toEqual('Hello World!')
})
})
Support for RESTfull requests by defining HTTP method (type). Also data, dataType and async are used for matching fake vs. real Ajax options:
fakeAjax({registrations:[
{url: '/example', type: 'put'}, // no match
{url: '/example', type: 'post'} // match!
]})
$.ajax({url: '/example', type: 'post', data: {user: 'dog'}, dataType: 'json'})
fakeAjax({registrations:[
{url: '/example', type: 'post', data: {user: 'dog'}}, // match!
{url: '/example', type: 'post', data: {user: 'cat'}} // no match
]})
$.ajax({url: '/example', type: 'post', data: {user: 'dog'}})
You can register fake ajax options in a list using fakeAjax({registrations:[options1, options2]})
and/or one by one using registerFakeAjax(options)
. You can easily mix and match both, e.g. registering some general options in beforeEach
and then some custom options in it
.
The context (with all registered fake Ajax options) will be cleared before each test.
You may inline the test data
fakeAjax({registrations:[{url: '/succeeds', successData: 'Jasmine FTW!'}]})
or load the test data using loadTestData
. You can add multiple blocks of fake html and then use any jQuery selector to pick the right one. Here we load the contents of .questions
from fake-ajax-fixture.html
:
fakeAjax({registrations:[{url: '/questions/list', successData: loadTestData('.questions', 'fake-ajax-fixture.html')}]})
and when you need the error handler to be called you can
fakeAjax({registrations:[{url: '/fails', errorMessage: 'argh'}]})
Fake response data in JSON format (simply a js map):
fakeAjax({registrations:[{url: '/user', successData: {name: 'John', age: 30}}]})
It should be straight forward to load fake JSON from an external file if you will:
fake-json.js:
var FakeJsons = {
first: {name: 'John', age: 30},
second: {foo: [{key: 1}, {key: 2}]}
}
// Load both files in spec runner html
my-spec.js:
registerFakeAjax({
url: '/example',
success: {
data: FakeJsons.second
}
})
There are 4 possible callback rules you can use (only one at a time): success
, successData
, error
and errorMessage
.
If you only need to define the success data you can use the simple successData
callback rule:
registerFakeAjax({url: '/example', successData: 'yay'})
However, if you need to be more specific with the success callback arguments you can use success
callback rule:
registerFakeAjax({url: '/example', success: {data: {name: 'John'}, status: 'ok', ...}})
If you only need to define the error message you can use the simple errorMessage
callback rule:
registerFakeAjax({url: '/example', errorMessage: 'crap'})
However, if you need to be more specific with the error callback arguments you can use error
callback rule:
registerFakeAjax({url: '/example', error: {xhr: {status: 500}, responseText: 'oh noez', ...}})
Again, there are many more examples in spec/fake-ajax-spec.js
.
Often, multiple Ajax calls are executed under the hood when e.g. clicking a link. fakeAjax
lets you define which calls will succeed and which will fail:
fakeAjax({registrations:[
{url: '/answers.*question2', successData: loadTestData('.answer2', 'fake-ajax-fixture.html')},
{url: '/authors.*answer2', errorMessage: 'author data not available'},
{url: '/onError', successData: 'Please try again later.'}
]})
You are not forced to define any context. Maybe you are only interested in what is sent to the server? Then you can use latestAjax
or latestAjaxWithUrlMatching
to get a handle to desired ajax options recorded during the test run:
expect(latestAjaxWithUrlMatching('first').data).toEqual({'param1': 'value1', 'param2': 'value2'})
expect(latestAjaxWithUrlMatching('second').url).toContain('foo=bar')
expect(latestAjax().url).toEqual('/third')
Warnings and errors during the test run are logged into the firebug console, so you should consider keeping it open.
Note: lib here means jasmine-fake-ajax-X.js
In short: put files in dependencies/
and lib/jasmine-fake-ajax.js
to your load path. You should be good to go. Probably works with other jQuery versions than in dependencies/
. However, please report if there are any problems.
Dependencies for using this lib:
- jQuery, the lib should work with 1.4.x, 1.5.x and 1.6.x, please report if you have any problems
- Jasmine
- the great underscore.js is used for embracing functional programming style in the lib
Dependencies for developing this lib and running the tests:
- jasmine-jquery for some tests that use DOM
- PhantomJS for running tests headless from command line
- Watchr for running all tests on any change to source files (using PhantomJS)
- currently only one piece of js is written in CoffeeScript but I'm planning to use it more
Tested with multiple versions of Firefox and Chrome. Both have very good development/debugging tools. Chrome seems to be a lot faster. Firefox should be ok out-of-the-box but if you want to use Chrome you must allow it to load local files:
open -a 'Google Chrome' --args --allow-file-access-from-files
- extract executable examples from executable spec
- rewrite with CoffeeScript!
Hope you enjoy, don't forget to follow me on twitter!