
can-fixture
can-fixture
intercepts an AJAX request and simulates
the response with a file or function. Use can-fixture
to:
- Develop JavaScript independently of the backend services.
- Test code that makes AJAX requests without needing a server.
- Simulate slow responses or difficult to reproduce error conditions.
can-fixture
is self contained and can be used without the rest of CanJS.
Play around with can-fixture in this JSBin!
- Install
- Basic Use
- API
fixture(ajaxSettings, requestHandler(...))
fixture(ajaxSettings, url)
fixture(ajaxSettings, data)
fixture(ajaxSettings, delay)
fixture(ajaxSettings, null)
fixture(methodAndUrl, url|data|requestHandler)
fixture(url, url|data|requestHandler)
fixture(fixtures)
fixture(restfulUrl, store)
fixture.store(baseItems, algebra)
fixture.store(count, makeItems, algebra)
Store
fixture.rand(min, max)
fixture.rand(choices, min, max)
fixture.delay
fixture.on
fixture.fixtures
Install
If you are using Browserify
or StealJS, install it with NPM:
npm install can-fixture --save-dev
Then import
, require
, steal
, or define
the "can-fixture"
module:
var fixture = require("can-fixture");
Basic Use
Use the fixture
function to trap settings on a XMLHttpRequest object to a request handler.
The following traps all GET
type requests to /service
and results in a responseText
of "{\"message\":\"Hello World\"}"
:
fixture({url: "/service", method: "get"}, function(request, response){
response({message: "Hello World"});
})
The fixture
function has a wide variety of signatures that allow more control or easier shorthands. The previous
example could be written like:
fixture("GET /service", function(request, response){
return {message: "Hello World"};
})
Or:
fixture("GET /service", {message: "Hello World"});
You can forward a request to another url:
fixture("GET /service", "/fixtures/service.json");
Multiple fixture rules can be setup at once like:
fixture({
"GET /service": {message: "Hello World"},
"POST /service": function(request, response){
response(401,"{type: 'unauthorized'}");
}
});
Remove a fixture by calling fixture
with null in place of a responseHandler:
fixture("GET /service", null);
Finally, use fixture.store
to create a can-connect like-data store that simulates a restful service connected to a data store. Use can-set to describe the service's parameters.
var todoAlgebra = new set.Algebra({
set.props.id("_id"),
set.props.boolean("completed"),
set.props.rangeInclusive("start","end"),
set.props.sort("orderBy"),
});
var todoStore = fixture.store([
{
_id : 1,
name : 'Do the dishes',
complete: true
}, {
_id : 2,
name : 'Walk the dog',
complete: false
}],
todoAlgebra );
fixture("/todos/{_id}", todoStore);
If your urls aren't restful you can wire up the store manually:
fixture({
"GET /todos": todoStore.getListData,
"POST /todos": todoStore.createData,
"GET /todos/{_id}": todoStore.getData,
"PUT /todos/{_id}": todoStore.updateData,
"DELETE /todos/{_id}": todoStore.deleteData
});
API
The fixture
function has multiple signatures, most based on convenience. However,
we'll start with the lowest-level API which everything else is based:
fixture(ajaxSettings, requestHandler(...))
If an XHR request matches ajaxSettings
, calls requestHandler
with
the XHR requests data. Makes the XHR request responds with the return value of
requestHandler
or the result of calling its response
argument.
ajaxSettings
- An object that is used to match values on an XHR object, namely the
url
and method
. url
can be templated like /todos/{_id}
.
requestHandler
- Handles the request and provides a response. The
next section details this function's use.
The following traps requests to GET /todos
and responds with an array of data:
fixture({method: "get", url: "/todos"},
function(request, response, headers, ajaxSettings){
return {
data: [
{id: 1, name: "dishes"},
{id: 2, name: "mow"}
]
};
})
When adding a fixture, it will remove any identical fixtures from the list of fixtures. The
last fixture added will be the first matched.
requestHandler(request, response(...), requestHeaders, ajaxSettings)
The request handler argument is called with:
request
- Information about the request. The request's data
property will
contain data from the request's querystring or request body.
response
- A callback function that provides response information. The
next section details this function's use.
requestHeaders
- Headers used to make the request.
ajaxSettings
- The settings object used to match this request.
Example:
fixture({method: "get", url: "/todos"},
function(request, response, headers, ajaxSettings){
request
}
});
$.ajax({ method: "get", url: "/todos?complete=true" })
Templated url
data will be added to the requestHandler
's request
argument's data
property:
fixture({url: "/todos/{action}"},
function(request, response, headers, ajaxSettings){
request
}
});
$.post("/todos/delete");
response(status, body, headers, statusText)
Used to detail a response.
status
- The HTTP response code. Ex: 200
.
body
- A JS object that will be serialized and set as the responseText of the XHR object, or
the raw string text that will be set as the responseText of the XHR object.
headers
- An object of HTTP response headers and values.
statusText
- The status text of the response. Ex: "ok"
for 200.
Example:
fixture({url: "/todos/{action}"},
function(request, response, headers, ajaxSettings){
response(
401,
{ message: "Unauthorized"},
{ "WWW-Authenticate": 'Basic realm="myRealm"'},
"unauthorized");
}
});
$.post("/todos/delete");
You don't have to provide every argument to response
. It can be called like:
response({ message: "Hello World"});
response(401, { message: "Unauthorized"});
response('{"message":"Unauthorized"}',{"WWW-Authenticate":'Basic realm="myRealm"'});
response(401, '{"message":"Unauthorized"}','unauthorized');
The default statusText
will be ok
for 200 <= status < 300, status === 304
and error
for everything else.
fixture(ajaxSettings, url)
Redirects the request to another url. This can be useful for simulating a response with a file.
fixture({url: "/tasks"}, "fixtures/tasks.json");
Placeholders available in the ajaxSettings
url will be available in the redirect url:
fixture({url: "/tasks/{id}"}, "fixtures/tasks/{id}.json");
fixture(ajaxSettings, data)
Responds with the JSON.stringify
result of data
.
fixture({url: "/tasks"}, {tasks: [{id: 1, complete: false}]});
fixture(ajaxSettings, delay)
Delays the ajax request from being made for delay
milliseconds.
fixture({url: "/tasks"}, 2000);
This doesn't simulate a response, but is useful for simulating slow connections.
fixture(ajaxSettings, null)
Removes the matching fixture from the list of fixtures.
fixture({url: "/tasks"}, "fixtures/tasks.json");
$.get("/tasks")
fixture({url: "/tasks"}, null);
$.get("/tasks")
fixture(methodAndUrl, url|data|requestHandler)
A short hand for creating an ajaxSetting
with a method
and url
.
fixture("GET /tasks", requestHandler );
fixture({method: "get", url: "/tasks"}, requestHandler );
The format is METHOD URL
.
fixture(url, url|data|requestHandler)
A short hand for creating an ajaxSetting
with just a url
.
fixture("/tasks", requestHandler);
fixture({url: "/tasks"}, requestHandler);
fixture(fixtures)
Create multiple fixtures at once.
- fixtures
{Object<methodAndUrl,url|data|requestHandler|store>}
- An mapping of methodAndUrl to
some response argument type.
fixture({
"POST /tasks": function(){
return {id: Math.random()}
},
"GET /tasks": {data: [{id: 1, name: "mow lawn"}]},
"/people": "fixtures/people.json"
});
fixture(restfulUrl, store)
Wire up a restful API scheme to a store.
var todoAlgebra = new set.Algebra();
var todoStore = fixture.store([
{ id: 1, name: 'Do the dishes'},
{ id: 2, name: 'Walk the dog'}
], todoAlgebra);
fixture("/api/todos/{id}", todoStore);
This is a shorthand for wiring up the todoStore
as follows:
fixture({
"GET /api/todos": todoStore.getListData,
"GET /api/todos/{id}": todoStore.getData,
"POST /api/todos": todosStore.createData,
"PUT /api/todos/{id}": todos.updateData,
"DELETE /api/todos/{id}": todos.destroyData
});
fixture.store(baseItems, algebra)
Create a store that starts with baseItems
for a service layer
described by algebra
.
- baseItems
{Array}
- An array of items that will populate the store.
- algebra
{can.Algebra}
- A description of the service layer's parameters.
var todoAlgebra = new set.Algebra({
set.props.id("_id"),
set.props.boolean("completed"),
set.props.rangeInclusive("start","end"),
set.props.sort("orderBy"),
});
var todoStore = fixture.store([
{
_id : 1,
name : 'Do the dishes',
complete: true
}, {
_id : 2,
name : 'Walk the dog',
complete: false
}],
todoAlgebra );
fixture("/todos/{_id}", todoStore);
fixture.store(count, makeItems, algebra)
Similar to fixture.store(baseItems, algebra)
, except that
it uses makeItems
to create count
entries in the store.
var todoAlgebra = new set.Algebra({ ... });
var todoStore = fixture.store(
1000,
function(i){
return {
_id : i+1,
name : 'Todo '+i,
complete: fixture.rand([true, false],1)[0]
}
},
todoAlgebra );
fixture("/todos/{_id}", todoStore);
Store
The following documents the methods on a store object returned by
fixture.store
.
Store.prototype.getListData(request, response)
A requestHandler
that gets multiple items from the store.
fixture("GET /api/todos", todoStore.getListData);
Store.prototype.getData(request, response)
A requestHandler
that gets a single item from the store.
fixture("GET /api/todos/{_id}", todoStore.getData);
Store.prototype.createData(request, response)
A requestHandler
that creates an item in the store.
fixture("POST /api/todos", todoStore.createData);
Store.prototype.updateData(request, response)
A requestHandler
that updates an item in the store.
fixture("PUT /api/todos/{_id}", todoStore.updateData);
Store.prototype.destroyData(request, response)
A requestHandler
that removes an item from the store.
fixture("DELETE /api/todos/{_id}", todoStore.destroyData)
Store.prototype.reset([baseItems])
Sets the items in the store to their original state or to baseItems
if it's passed.
var todoStore = fixture.store(
[{id: 1, name: "dishes"}],
new set.Algebra());
fixture("/todos/{id}", todoStore)
todoStore.getList({}).length
$.ajax({url: "todos/1", method: "delete"}).then(function(){
return todoStore.getList({}).length
}).then(function(){
todoStore.reset();
todoStore.getList({}).length
});
Store.prototype.get(params)
Returns a single item's data from the store.
todoStore.get({id: 1})
Store.prototype.getList(set)
Returns the matching items from the store like: {data: [...]}
.
todoStore.get({name: "dishes"})
fixture.rand(min, max)
Returns a random integer in the range [min, max]. If only one argument is provided,
returns a random integer from [0, max].
fixture.rand(1, 10)
fixture.rand(10)
fixture.rand(choices, min, max)
An array of between min and max random items from choices. If only min
is
provided, max
will equal min
. If both max
ad min
are not provided,
min
will be 1 and max
will be choices.length
.
fixture.rand(["a","b","c"])
fixture.rand(["a","b","c"])
fixture.rand(["a","b","c"],1)
fixture.rand(["a","b","c"],1)[0]
fixture.rand(["a","b","c"],2,3)
fixture.delay
Sets the delay until a response is fired in milliseconds.
fixture.delay = 1000;
fixture.on
Turns the fixtures on or off. Defaults to true
for on.
fixture.on = false;
To remove a fixture you can also use fixture(ajaxSetting, null)
.
fixture.fixtures
The list of currently active fixtures.