Mock at a higher level; add Zepto tests
This commit is contained in:
parent
369a72647b
commit
b987b61da2
1355
frameworks/zepto.js
Normal file
1355
frameworks/zepto.js
Normal file
File diff suppressed because it is too large
Load Diff
130
lib/mock-ajax.js
130
lib/mock-ajax.js
@ -31,25 +31,30 @@
|
||||
|
||||
*/
|
||||
|
||||
// Jasmine-Ajax interface
|
||||
var ajaxRequests = [];
|
||||
(function(exports) {
|
||||
// Jasmine-Ajax interface
|
||||
exports.ajaxRequests = [];
|
||||
|
||||
function mostRecentAjaxRequest() {
|
||||
if (ajaxRequests.length > 0) {
|
||||
return ajaxRequests[ajaxRequests.length - 1];
|
||||
} else {
|
||||
return null;
|
||||
exports.mostRecentAjaxRequest = function() {
|
||||
if (ajaxRequests.length > 0) {
|
||||
return ajaxRequests[ajaxRequests.length - 1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearAjaxRequests() {
|
||||
ajaxRequests = [];
|
||||
}
|
||||
exports.clearAjaxRequests = function() {
|
||||
exports.ajaxRequests = [];
|
||||
}
|
||||
|
||||
// Fake XHR for mocking Ajax Requests & Responses
|
||||
|
||||
exports.FakeXMLHttpRequest = function() {
|
||||
ajaxRequests.push(this);
|
||||
};
|
||||
|
||||
// Fake XHR for mocking Ajax Requests & Responses
|
||||
function FakeXMLHttpRequest() {
|
||||
var extend = Object.extend || jQuery.extend;
|
||||
extend(this, {
|
||||
extend(FakeXMLHttpRequest.prototype, {
|
||||
requestHeaders: {},
|
||||
|
||||
open: function() {
|
||||
@ -114,12 +119,13 @@ function FakeXMLHttpRequest() {
|
||||
this.responseText = response.responseText || "";
|
||||
this.readyState = 4;
|
||||
this.responseHeaders = response.responseHeaders ||
|
||||
{"Content-type": response.contentType || "application/json" };
|
||||
{"Content-type": response.contentType || "application/json" };
|
||||
// uncomment for jquery 1.3.x support
|
||||
// jasmine.Clock.tick(20);
|
||||
|
||||
this.onreadystatechange();
|
||||
},
|
||||
|
||||
responseTimeout: function() {
|
||||
this.readyState = 4;
|
||||
jasmine.Clock.tick(jQuery.ajaxSettings.timeout || 30000);
|
||||
@ -127,67 +133,51 @@ function FakeXMLHttpRequest() {
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
exports.jasmine.Ajax = {
|
||||
isInstalled: function() {
|
||||
return jasmine.Ajax.installed === true;
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (!jasmine.Ajax.isInstalled()) {
|
||||
throw new Error("Mock ajax is not installed, use jasmine.Ajax.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
jasmine.Ajax = {
|
||||
useMock: function() {
|
||||
if (!jasmine.Ajax.isInstalled()) {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Ajax.uninstallMock);
|
||||
|
||||
isInstalled: function() {
|
||||
return jasmine.Ajax.installed === true;
|
||||
},
|
||||
jasmine.Ajax.installMock();
|
||||
}
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (!jasmine.Ajax.isInstalled()) {
|
||||
throw new Error("Mock ajax is not installed, use jasmine.Ajax.useMock()");
|
||||
}
|
||||
},
|
||||
installMock: function() {
|
||||
jasmine.Ajax.installTopLevel();
|
||||
jasmine.Ajax.installed = true;
|
||||
},
|
||||
|
||||
useMock: function() {
|
||||
if (!jasmine.Ajax.isInstalled()) {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Ajax.uninstallMock);
|
||||
installTopLevel: function() {
|
||||
jasmine.Ajax.mode = 'toplevel';
|
||||
jasmine.Ajax.real = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = FakeXMLHttpRequest;
|
||||
},
|
||||
|
||||
jasmine.Ajax.installMock();
|
||||
}
|
||||
},
|
||||
uninstallMock: function() {
|
||||
jasmine.Ajax.assertInstalled();
|
||||
window.XMLHttpRequest = jasmine.Ajax.real;
|
||||
jasmine.Ajax.reset();
|
||||
},
|
||||
|
||||
installMock: function() {
|
||||
if (typeof jQuery != 'undefined') {
|
||||
jasmine.Ajax.installJquery();
|
||||
} else {
|
||||
throw new Error("jasmine.Ajax currently only supports jQuery");
|
||||
}
|
||||
jasmine.Ajax.installed = true;
|
||||
},
|
||||
reset: function() {
|
||||
jasmine.Ajax.installed = false;
|
||||
jasmine.Ajax.mode = null;
|
||||
jasmine.Ajax.real = null;
|
||||
},
|
||||
|
||||
installJquery: function() {
|
||||
jasmine.Ajax.mode = 'jQuery';
|
||||
jasmine.Ajax.real = jQuery.ajaxSettings.xhr;
|
||||
jQuery.ajaxSettings.xhr = jasmine.Ajax.jQueryMock;
|
||||
installed: false,
|
||||
mode: null
|
||||
};
|
||||
})(window);
|
||||
|
||||
},
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Ajax.assertInstalled();
|
||||
if (jasmine.Ajax.mode == 'jQuery') {
|
||||
jQuery.ajaxSettings.xhr = jasmine.Ajax.real;
|
||||
}
|
||||
jasmine.Ajax.reset();
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
jasmine.Ajax.installed = false;
|
||||
jasmine.Ajax.mode = null;
|
||||
jasmine.Ajax.real = null;
|
||||
},
|
||||
|
||||
jQueryMock: function() {
|
||||
var newXhr = new FakeXMLHttpRequest();
|
||||
ajaxRequests.push(newXhr);
|
||||
return newXhr;
|
||||
},
|
||||
|
||||
installed: false,
|
||||
mode: null
|
||||
};
|
||||
|
@ -34,33 +34,22 @@ describe("jasmine.Ajax", function() {
|
||||
});
|
||||
|
||||
describe("installMock", function() {
|
||||
describe("when using jQuery", function() {
|
||||
describe("when using a top-level replacement", function() {
|
||||
|
||||
it("installs the mock", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jQuery.ajaxSettings.xhr).toBe(jasmine.Ajax.jQueryMock);
|
||||
expect(window.XMLHttpRequest).toBe(FakeXMLHttpRequest);
|
||||
});
|
||||
|
||||
it("saves a reference to jQuery.ajaxSettings.xhr", function() {
|
||||
var jqueryAjax = jQuery.ajaxSettings.xhr;
|
||||
it("saves a reference to the browser's XHR", function() {
|
||||
var xhr = window.XMLHttpRequest;
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jasmine.Ajax.real).toBe(jqueryAjax);
|
||||
expect(jasmine.Ajax.real).toBe(xhr);
|
||||
});
|
||||
|
||||
it("sets mode to 'jQuery'", function() {
|
||||
it("sets mode to 'toplevel'", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jasmine.Ajax.mode).toEqual("jQuery");
|
||||
});
|
||||
});
|
||||
|
||||
describe("when using any other library", function() {
|
||||
it("raises an exception", function() {
|
||||
var jquery = jQuery;
|
||||
jQuery = undefined;
|
||||
|
||||
expect(function(){ jasmine.Ajax.installMock(); }).toThrow("jasmine.Ajax currently only supports jQuery");
|
||||
|
||||
jQuery = jquery;
|
||||
expect(jasmine.Ajax.mode).toEqual("toplevel");
|
||||
});
|
||||
});
|
||||
|
||||
@ -72,14 +61,14 @@ describe("jasmine.Ajax", function() {
|
||||
});
|
||||
|
||||
describe("uninstallMock", function() {
|
||||
describe("when using jQuery", function() {
|
||||
it("returns ajax control to jQuery", function() {
|
||||
var jqueryAjax = jQuery.ajaxSettings.xhr;
|
||||
describe("when using toplevel", function() {
|
||||
it("returns ajax control to the browser object", function() {
|
||||
var xhr = window.XMLHttpRequest;
|
||||
|
||||
jasmine.Ajax.installMock();
|
||||
jasmine.Ajax.uninstallMock();
|
||||
|
||||
expect(jQuery.ajaxSettings.xhr).toBe(jqueryAjax);
|
||||
expect(window.XMLHttpRequest).toBe(xhr);
|
||||
});
|
||||
});
|
||||
|
||||
@ -124,10 +113,3 @@ describe("jasmine.Ajax", function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function withoutJquery(spec) {
|
||||
var jqueryRef = jQuery;
|
||||
jQuery = undefined;
|
||||
spec.apply(this);
|
||||
jQuery = jqueryRef;
|
||||
}
|
||||
|
368
spec/javascripts/mock-ajax-zepto-spec.js
Normal file
368
spec/javascripts/mock-ajax-zepto-spec.js
Normal file
@ -0,0 +1,368 @@
|
||||
describe("Jasmine Mock Ajax (for Zepto)", function() {
|
||||
var request, anotherRequest, response;
|
||||
var success, error, complete;
|
||||
var sharedContext = {};
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.useMock();
|
||||
|
||||
success = jasmine.createSpy("onSuccess");
|
||||
error = jasmine.createSpy("onFailure");
|
||||
complete = jasmine.createSpy("onComplete");
|
||||
});
|
||||
|
||||
describe("when making a request", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
});
|
||||
|
||||
it("should store URL and transport", function() {
|
||||
expect(request.url).toEqual("example.com/someApi");
|
||||
});
|
||||
|
||||
it("should queue the request", function() {
|
||||
expect(ajaxRequests.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("should allow access to the queued request", function() {
|
||||
expect(ajaxRequests[0]).toEqual(request);
|
||||
});
|
||||
|
||||
describe("and then another request", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
anotherRequest = mostRecentAjaxRequest();
|
||||
});
|
||||
|
||||
it("should queue the next request", function() {
|
||||
expect(ajaxRequests.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("should allow access to the other queued request", function() {
|
||||
expect(ajaxRequests[1]).toEqual(anotherRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mostRecentAjaxRequest", function () {
|
||||
|
||||
describe("when there is one request queued", function () {
|
||||
it("should return the request", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(request);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there is more than one request", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
anotherRequest = mostRecentAjaxRequest();
|
||||
});
|
||||
|
||||
it("should return the most recent request", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(anotherRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there are no requests", function () {
|
||||
beforeEach(function() {
|
||||
clearAjaxRequests();
|
||||
});
|
||||
|
||||
it("should return null", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearAjaxRequests()", function () {
|
||||
beforeEach(function() {
|
||||
clearAjaxRequests();
|
||||
});
|
||||
|
||||
it("should remove all requests", function() {
|
||||
expect(ajaxRequests.length).toEqual(0);
|
||||
expect(mostRecentAjaxRequest()).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when simulating a response with request.response", function () {
|
||||
describe("and the response is Success", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: 'text',
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
response = {status: 200, contentType: "text/html", responseText: "OK!"};
|
||||
request.response(response);
|
||||
|
||||
sharedContext.responseCallback = success;
|
||||
sharedContext.status = response.status;
|
||||
sharedContext.contentType = response.contentType;
|
||||
sharedContext.responseText = response.responseText;
|
||||
});
|
||||
|
||||
it("should call the success handler", function() {
|
||||
expect(success).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call the failure handler", function() {
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
sharedAjaxResponseBehaviorForZepto_Success(sharedContext);
|
||||
});
|
||||
|
||||
describe("and the response is Success, but with JSON", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
var responseObject = {status: 200, contentType: "application/json", responseText: '{"foo":"bar"}'};
|
||||
|
||||
request.response(responseObject);
|
||||
|
||||
sharedContext.responseCallback = success;
|
||||
sharedContext.status = responseObject.status;
|
||||
sharedContext.contentType = responseObject.contentType;
|
||||
sharedContext.responseText = responseObject.responseText;
|
||||
|
||||
response = success.mostRecentCall.args[2];
|
||||
});
|
||||
|
||||
it("should call the success handler", function() {
|
||||
expect(success).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call the failure handler", function() {
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return a JavaScript object", function() {
|
||||
expect(success.mostRecentCall.args[0]).toEqual({foo: "bar"});
|
||||
});
|
||||
|
||||
sharedAjaxResponseBehaviorForZepto_Success(sharedContext);
|
||||
});
|
||||
|
||||
describe("the content type defaults to application/json", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
response = {status: 200, responseText: '{"foo": "valid JSON, dammit."}'};
|
||||
request.response(response);
|
||||
|
||||
sharedContext.responseCallback = success;
|
||||
sharedContext.status = response.status;
|
||||
sharedContext.contentType = "application/json";
|
||||
sharedContext.responseText = response.responseText;
|
||||
});
|
||||
|
||||
it("should call the success handler", function() {
|
||||
expect(success).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call the failure handler", function() {
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
sharedAjaxResponseBehaviorForZepto_Success(sharedContext);
|
||||
});
|
||||
|
||||
describe("and the status/response code is 0", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: "text",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
response = {status: 0, responseText: '{"foo": "whoops!"}'};
|
||||
request.response(response);
|
||||
|
||||
sharedContext.responseCallback = error;
|
||||
sharedContext.status = 0;
|
||||
sharedContext.contentType = 'application/json';
|
||||
sharedContext.responseText = response.responseText;
|
||||
});
|
||||
|
||||
it("should call the success handler", function() {
|
||||
expect(success).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call the failure handler", function() {
|
||||
expect(error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
sharedAjaxResponseBehaviorForZepto_Failure(sharedContext);
|
||||
});
|
||||
});
|
||||
|
||||
describe("and the response is error", function () {
|
||||
beforeEach(function() {
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: "text",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
response = {status: 500, contentType: "text/html", responseText: "(._){"};
|
||||
request.response(response);
|
||||
|
||||
sharedContext.responseCallback = error;
|
||||
sharedContext.status = response.status;
|
||||
sharedContext.contentType = response.contentType;
|
||||
sharedContext.responseText = response.responseText;
|
||||
});
|
||||
|
||||
it("should not call the success handler", function() {
|
||||
expect(success).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the failure handler", function() {
|
||||
expect(error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
sharedAjaxResponseBehaviorForZepto_Failure(sharedContext);
|
||||
});
|
||||
|
||||
describe('when simulating a response with request.responseTimeout', function() {
|
||||
beforeEach(function() {
|
||||
jasmine.Clock.useMock();
|
||||
|
||||
Zepto.ajax({
|
||||
url: "example.com/someApi",
|
||||
type: "GET",
|
||||
dataType: "text",
|
||||
success: success,
|
||||
complete: complete,
|
||||
error: error
|
||||
});
|
||||
request = mostRecentAjaxRequest();
|
||||
response = {contentType: "text/html", responseText: "(._){"};
|
||||
request.responseTimeout(response);
|
||||
|
||||
sharedContext.responseCallback = error;
|
||||
sharedContext.status = response.status;
|
||||
sharedContext.contentType = response.contentType;
|
||||
sharedContext.responseText = response.responseText;
|
||||
});
|
||||
|
||||
it("should not call the success handler", function() {
|
||||
expect(success).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the failure handler", function() {
|
||||
expect(error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the complete handler", function() {
|
||||
expect(complete).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function sharedAjaxResponseBehaviorForZepto_Success(context) {
|
||||
describe("the success response", function () {
|
||||
var xhr;
|
||||
beforeEach(function() {
|
||||
xhr = context.responseCallback.mostRecentCall.args[2];
|
||||
});
|
||||
|
||||
it("should have the expected status code", function() {
|
||||
expect(xhr.status).toEqual(context.status);
|
||||
});
|
||||
|
||||
it("should have the expected content type", function() {
|
||||
expect(xhr.getResponseHeader('Content-type')).toEqual(context.contentType);
|
||||
});
|
||||
|
||||
it("should have the expected response text", function() {
|
||||
expect(xhr.responseText).toEqual(context.responseText);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sharedAjaxResponseBehaviorForZepto_Failure(context) {
|
||||
describe("the failure response", function () {
|
||||
var xhr;
|
||||
beforeEach(function() {
|
||||
xhr = context.responseCallback.mostRecentCall.args[0];
|
||||
});
|
||||
|
||||
it("should have the expected status code", function() {
|
||||
expect(xhr.status).toEqual(context.status);
|
||||
});
|
||||
|
||||
it("should have the expected content type", function() {
|
||||
expect(xhr.getResponseHeader('Content-type')).toEqual(context.contentType);
|
||||
});
|
||||
|
||||
it("should have the expected response text", function() {
|
||||
expect(xhr.responseText).toEqual(context.responseText);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
src_dir: .
|
||||
|
||||
src_files:
|
||||
- frameworks/zepto.js
|
||||
- frameworks/jquery.js
|
||||
- lib/mock-ajax.js
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user