Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
jquery-mockjax
Advanced tools
Mockjax. The jQuery Mockjax Plugin provides a simple and extremely flexible interface for mocking or simulating ajax requests and responses.
http://github.com/jakerella/jquery-mockjax/
jQuery Mockjax provides request/response mocking for ajax requests using the jQuery API and provides all standard behaviors in the request/response flow.
You may report any issues you may find in the github issue tracking.
Table of Contents
Most backend developers are familiar with the concepts of mocking objects or stubbing in methods for unit testing. For those not familiar with mocking, it's the simulation of an interface or API for testing or integration development purposes. Mocking with front-end development though is still quite new. Mockjax gives front end developers the ability to define ajax requests that should be mocked out, as well as how those requests should be responded to. These mocks can be extremely simple or quite complex, representing the entire request-response workflow.
At appendTo we developed a lot of applications which use RESTFUL web services, but much of the time those services are not yet created. We spec out the service contract and data format at the beginning of a project and develop the front-end interface against mock data while the back end team builds the production services.
This plugin was originally developed by appendTo in March 2010 and the team has been using it in many projects since.
Mockjax consists of just a few methods, each listed below. You'll find plenty of examples in the sections below, but if you're looking for a specific option, checkout this list:
Number $.mockjax(/* Object */ options)
options
: [Object] Defines the settings to use for the mocked request
url
: [String | RegExp] Specifies the url of the request that the data should be mocked for. If it is a string and contains any asterisks ( *
), they will be treated as a wildcard by translating to a regular expression. Any *
will be replaced with .+
. If you run into trouble with this shortcut, switch to using a full regular expression instead of a string and asterisk combinationdata
: [Object] In addition to the URL, match parameterstype
: [String] Specify what HTTP method to match, usually GET or POST. Case-insensitive, so get
and post
also workheaders
: [Object] Keys will be simulated as additional headers returned from the server for the request (NOTE: This is NOT used to match request headers!)status
: [Number] An integer that specifies a valid server response code. This simulates a server response codestatusText
: [String] Specifies a valid server response code description. This simulates a server response code descriptionresponseTime
: [Number] An integer that specifies a simulated network and server latency (in milliseconds)isTimeout
: [Boolean] Determines whether or not the mock will force a timeout on the requestcontentType
: [String] Specifies the content type for the responseresponse
: [Function] A function that accepts the request settings and allows for the dynamic setting of response settings (including the body of the response) upon each request (see examples below)responseText
: [String] Specifies the mocked text, or a mocked object literal, for the requestresponseXML
: [String] Specifies the mocked XML for the requestproxy
: [String] Specifies a path to a file, from which the contents will be returned for the requestlastModified
: [String] A date string specifying the mocked last-modified time for the request. This is used by $.ajax
to determine if the requested data is new since the last requestetag
: [String] Specifies a unique identifier referencing a specific version of the requested data. This is used by $.ajax
to determine if the requested data is new since the last request. (see HTTP_ETag)onAfterSuccess
: [Function] A callback that will be called after the success method has been called, this is useful to check a condition after the call has been completedonAfterError
: [Function] A callback that will be called after the error method has been called, this is useful to check a condition after the call has been completedonAfterComplete
: [Function] Similar to onAfterSuccess, but will be executed after the complete method has been calledObject $.mockjax.handler(/* Number */ id)
id
void $.mockjax.clear([/* Number */ id])
id
is provided, the handler with that ID is cleared (that is, requests matching it will no longer do so, the hnadler is completely removed)id
is provided, all handlers are cleared, resetting Mockjax to its initial stateArray<Object> $.mockjax.mockedAjaxCalls()
$.mockjax()
functionArray<Object> $.mockjax.unfiredHandlers()
$.ajax()
call then it will not appear in this arrayArray<Object> $.mockjax.unmockedAjaxCalls()
$.ajax({...})
Our first example will be for a simple REST service for a fortune app
with the REST endpoint being /restful/fortune
which returns the
following JSON message:
{
"status": "success",
"fortune" : "Are you a turtle?"
}
To pull the fortune into our page, we'd use the following HTML and jQuery code:
<!DOCTYPE html>
<html>
<head>
<title>Fortune App</title>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
</head>
<body>
<div id="fortune"></div>
</body>
</html>
$.getJSON("/restful/fortune", function(response) {
if ( response.status == "success") {
$("#fortune").html( "Your fortune is: " + response.fortune );
} else {
$("#fortune").html( "Things do not look good, no fortune was told" );
}
});
At this point if we were to run this code it would fail since the REST service has yet to be implemented. This is where the benefit of the Mockjax plugin starts to pay off. The first step in using Mockjax is to include the plugin by just adding a regular script tag:
<head>
...
<script src="vendor/jquery.mockjax.js"></script>
</head>
Once you have that included, you can start intercepting Ajax requests and mocking the responses. So let's mock out the service by including the following code:
$.mockjax({
url: "/restful/fortune",
responseText: {
status: "success",
fortune: "Are you a mock turtle?"
}
});
Defining a JSON string inline requires a JSON.stringify()
method to be
available. For some browsers you may need to include
json2.js,
which is included in the lib
folder. However, you could also simply
provide an already stringified version of your JSON in the responseText
property.
If you plan on mocking xml responses, you may also have to include
jquery.xmldom.js
, which can also be found in the lib
folder.
What Mockjax does at this point is replace the $.ajax()
method with a
wrapper that transparently checks the URL being requested. If the URL
matches one defined by $.mockjax()
, it intercepts the request
and sets up a mock XMLHttpRequest
object before executing the
jQuery.ajax()
handler. Otherwise, the request is handed back to the
native $.ajax()
method for normal execution. One benefit in this
implementation detail is that by simulating the XMLHttpRequest
object,
the plugin continues to make use of jQuery's native ajax handling, so
there are no concerns with implementing a custom Ajax workflow.
As you write code to mock responses, there's great value in the fact that there are no modifications required to production code. The mocks can be transparently inserted. This provides easy integration into most frameworks by including the plugin and mock definitions through your build framework. It's also possible to include it at run time by listening for a query string flag and injecting the plugin and definitions.
Now let's look at the various approaches to defining mocks as offered by the plugin. The sections below feature an extensive overview of the flexibility in Mockjax and creating responses.
jQuery is able to handle and parse Text
, HTML
, JSON
, JSONP
,
Script
and XML
data formats and Mockjax is able to mock any of those
formats. Two things to note: depending upon how you mock out JSON
and
JSONP
you may need to include json2.js
for the JSON.stringify()
method (older browsers only, typically). Additionally
if you mock XML inline, you'll need to include the xmlDOM
plugin that transforms a string of XML into a DOM object. However, if you use
the proxy approach outlined below then there should be no need to include either
the JSON or XMLDOM plugins in any case.
The first thing you need to do when mocking a request is define the URL end-point to intercept and mock. As with our example above this can be a simple string:
$.mockjax({
url: "/url/to/rest-service"
});
or contain a *
as a wildcard:
$.mockjax({
// Matches /data/quote, /data/tweet etc.
url: "/data/*"
});
or a full regular expression:
$.mockjax({
// Matches /data/quote, /data/tweet but not /data/quotes
url: /^\/data\/(quote|tweet)$/i
});
You can also match against the data option in addition to url:
$.mockjax({
url: "/rest",
data: { action: "foo" }
});
To capture URL parameters, use a capturing regular expression for the
URL and a urlParams
array to indicate, ordinally, the names of the
paramters that will be captured:
$.mockjax({
// matches /author/{any number here}/isbn/{any number with dashes here}
// for example: "/author/1234/isbn/1234-5678-9012-0"
url: /^\/author\/([\d]+)\/isbn\/([\d\-]+)$/,
// names of matching params
urlParams: ["authorID", "isbnNumber"],
response: function (settings) {
var authorID = settings.urlParams.authorID;
var isbnNumber = settings.urlParams.isbnNumber;
// etc...
}
});
The second step is to define the type and content of the response. The two main
properties you will be dealing with are either responseText
or
responseXML
. These properties mirror the native XMLHttpRequest
object properties that are set during a live response. There are three
different patterns for specifying the responses: Inline, Proxy, and
Callback.
A simple text response would be:
$.mockjax({
url: "/restful/api",
responseText: "A text response from the server"
});
A simple JSON response would be:
$.mockjax({
url: "/restful/api",
// You may need to include the [json2.js](https://raw.github.com/douglascrockford/JSON-js/master/json2.js) library for older browsers
responseText: { "foo": "bar" }
});
Also note that a JSON response is really just a text response that jQuery will
parse as JSON for you (and return a JSOn object to the success
and complete
callbacks).
A simple XML response would be:
$.mockjax({
url: "/restful/api",
// Need to include the xmlDOM plugin to have this translated into a DOM object
responseXML: "<document><quote>Hello world!</quote></document>"
});
As you can see, if you have a significant amount of data being mocked this becomes unwieldy. So that brings us to the next pattern: the proxy.
In this example below, the Mockjax plugin will intercept requests for
/restful/api
and redirect them to /mocks/data.json
:
$.mockjax({
url: "/restful/api",
proxy: "/mocks/data.json"
});
The /mocks/data.json
file can have any valid JSON content you want, and allows
you to maintain that mock data in its own file for maintainability.
In the final response pattern, we can define a callback function on the
response
property and have it set responseText
or responseXML
as
needed:
$.mockjax({
url: "/restful/api",
response: function(settings) {
// Investigate the `settings` to determine the response...
this.responseText = "Hello world!";
}
});
The default version of this callback is synchronous. If you provide both parameters to the callback function, you can use asynchronous code to set the dynamic response.
$.mockjax({
url: '/restful/api',
response: function(settings, done) {
var self = this;
someAsyncMethod(function(data){
self.responseText = data;
done();
});
}
});
Note that the callback is given the settings provided to the $.mockjax({...})
method merged with any Ajax settings defined by jQuery or your application. This
allows you to thoroughly investigate the request before setting the response
body (or headers).
At this point we've looked at a series of basic mocking techniques with Mockjax and will now unpack some of the additional functionality contained in the plugin.
Simulating network and server latency for a mock is as simple as adding
a responseTime
property to your mock definition:
$.mockjax({
url: "/restful/api",
// Simulate a network latency of 750ms
responseTime: 750,
responseText: "A text response from the server"
});
It's also possible to simulate response statuses other than 200 (default
for Mockjax) by simply adding a status
property.
$.mockjax({
url: "/restful/api",
// Server 500 error occurred
status: 500,
responseText: "A text response from the server"
});
These forced error status codes will be handled just as if the server had
returned the error: the error
callback will get executed with the proper
arguments.
You can set the content type to associate with the mock response, in the example below, we're setting a JSON content type.
$.mockjax({
url: "/restful/api",
contentType: "application/json",
responseText: {
hello: "World!"
}
});
Additional HTTP Response Headers may be provided by setting a key in the headers object literal:
$.mockjax({
url: "/restful/api",
contentType: "application/json",
responseText: {
hello: "World!"
},
headers: {
etag: "xyz123"
}
});
In some situations, all of your REST calls are based upon a URL schema.
Mockjax has the ability for you to specify a callback function that is
handed the $.ajax
request settings. The callback function may then
either return false to allow the request to be handled natively, or
return an object literal with relevant Mockjax parameters set. Below is
an example that rewrites all Ajax requests to proxy to static mocks:
$.mockjax(function(settings) {
// settings.url might be: "/restful/<service>" such as "/restful/user"
var service = settings.url.match(/\/restful\/(.*)$/);
if ( service ) {
return {
proxy: "/mocks/" + service[1] + ".json"
};
}
// If you get here, there was no url match
return;
});
In some situations, you may need access to the request headers to determine
matching or response bodies. To do this, you will need to specify a
callback function that is handed the $.ajax
request settings:
$.mockjax(function( requestSettings ) {
// Here is our manual URL matching...
if ( requestSettings.url === "/restful/user" ) {
// We have a match, so we return a response callback...
return {
response: function( origSettings ) {
// now we check the request headers, which may be set directly
// on the xhr object through an ajaxSetup() call or otherwise:
if ( requestSettings.headers["Authentication"] === "some-token" ) {
this.responseText = { user: { id: 13 } };
} else {
this.status = 403;
this.responseText = "You are not authorized";
}
}
};
}
// If you get here, there was no url match
return;
});
Because of the way Mockjax was implemented, it takes advantage of
jQuery's internal timeout handling for requests. But if you'd like to
force a timeout for a request you can do so by setting the isTimeout
property to true:
$.mockjax({
url: '/restful/api',
responseTime: 1000,
isTimeout: true
});
It's also possible to dynamically generate the response text upon each
request by implementing a callback function on the response
parameter:
$.mockjax({
url: "/restful/webservice",
dataType: "json",
response: function(settings) {
this.responseText = {
randomText: "random " + Math.random()
};
}
});
Many of the examples above mock a json
response. You can also mock xml
:
$.mockjax({
url: "/some/xml",
dataType: "xml",
responseXML: "<document><say>Hello world XML</say></document>"
});
(Don't forget that it's likely you'll need the xmlDOM
library as well!)
And html
:
$.mockjax({
url: "/some/webservice",
dataType: "html",
responseText: "<div>Hello there</div>"
});
If you need to perform some actions after a call has completed you can
use one of the onAfter{Xxxxx}
options. For example, to fire a method when
a request completes (either successfully or not):
$.mockjax({
url: "/api/end/point",
onAfterComplete: function() {
// do any required cleanup
}
});
It is also possible to define the global defaults for all Mockjax
requests by overwriting the $.mockjaxSettings
object. By default the
settings are as follows:
{
logging: true,
status: 200,
statusText: "OK",
responseTime: 500,
isTimeout: false,
throwUnmocked: false,
contentType: "text/plain",
response: "",
responseText: "",
responseXML: "",
proxy: "",
proxyType: "GET",
lastModified: null,
etag: "",
headers: {
etag: "IJF@H#@923uf8023hFO@I#H#",
"content-type" : "text/plain"
}
}
To overwrite a particular settings such as the default content-type
, you
would do the following:
$.mockjaxSettings.contentType = "application/json";
If you need to reset the Mockjax handlers you've added, just call
$.mockjax.clear()
. This will NOT reset the $.mockjaxSettings
!
$.mockjax.clear();
You can also clear individual mock handlers using their ID:
var id = $.mockjax({
...
});
$.mockjax.clear(id);
We strive to ensure that Mockjax is tested on the furthest patch version of all
minor (and major) versions of jQuery beginning with 1.3.2 going all the way
through 2.x. In other words, we don't test 1.6.1, but rather 1.6.4 (the furthest
patch version on the 1.6.x line). The QUnit tests in the /test
directory include
links to each version of jQuery tested in the header.
Note that jQuery Mockjax generally supports whatever browser jQuery supports. However, it is important to understand that various versions of jQuery have dropped support for different versions of browsers over the years. The point is, be sure to test on the browser versions you support!
We use virtual machines to test current versions of the browsers below. In addition, we test the minimum version specified next to the browser (with the exception of IE which specifies the versions we test).
Please note that while we strive to keep master
as bug free as possible, we do
not necessarily run tests in all of the above browsers for every single commit. We
do, however, ensure all tests are passing before tagging a release.
Please read the CHANGELOG for a list of changes per release.
Note that all releases are tagged in Github for easy reference, the master
branch
should not be considered a stable release!
Copyright (c) 2014 appendTo, Jordan Kasper
NOTE: This repository was taken over by Jordan Kasper (@jakerella) October, 2014
Dual licensed under the MIT or GPL licenses: http://opensource.org/licenses/MIT http://www.gnu.org/licenses/gpl-2.0.html
We welcome any contributions by the community, whether in the form of a Pull Request, issue submission and comments, or just sharing on social media!
If you want to contribute code to the project, please read our Contribution guidelines to see what you need to do to get your Pull Request ready for merging.
All pull requests are reviewed by the wonderful collaborators on this project:
FAQs
The jQuery Mockjax Plugin provides a simple and extremely flexible interface for mocking or simulating ajax requests and responses.
We found that jquery-mockjax demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.