Rework jasmine ajax to behave more like the jasmine clock and spys
- use an instance of MockAjax for nicer tests - the only global install is `mockAjax` - mockAjax has a `requests` to track requests that have been made - mockAjax has a `stubs` to track stubs that have been registered - use just `install` and `uninstall` to be consistent with clock
This commit is contained in:
parent
7900fc3e18
commit
c2a02dbdf6
350
lib/mock-ajax.js
350
lib/mock-ajax.js
@ -31,28 +31,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var jasmineAjaxInterface = {
|
||||
// Jasmine-Ajax interface
|
||||
ajaxRequests: [],
|
||||
ajaxStubs: [],
|
||||
|
||||
mostRecentAjaxRequest: function() {
|
||||
if (ajaxRequests.length > 0) {
|
||||
return ajaxRequests[ajaxRequests.length - 1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
clearAjaxRequests: function() {
|
||||
ajaxRequests = [];
|
||||
},
|
||||
|
||||
clearAjaxStubs: function() {
|
||||
ajaxStubs = [];
|
||||
}
|
||||
};
|
||||
|
||||
function extend(destination, source) {
|
||||
for (var property in source) {
|
||||
destination[property] = source[property];
|
||||
@ -60,182 +38,196 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
return destination;
|
||||
}
|
||||
|
||||
if (typeof window === "undefined" && typeof exports === "object") {
|
||||
extend(exports, jasmineAjaxInterface);
|
||||
} else {
|
||||
extend(window, jasmineAjaxInterface);
|
||||
}
|
||||
function MockAjax(global) {
|
||||
var requestTracker = new RequestTracker(),
|
||||
stubTracker = new StubTracker(),
|
||||
realAjaxFunction = global.XMLHttpRequest,
|
||||
mockAjaxFunction = fakeRequest(requestTracker, stubTracker);
|
||||
|
||||
// Fake XHR for mocking Ajax Requests & Responses
|
||||
this.install = function() {
|
||||
global.XMLHttpRequest = mockAjaxFunction;
|
||||
};
|
||||
|
||||
window.FakeXMLHttpRequest = function() {
|
||||
ajaxRequests.push(this);
|
||||
};
|
||||
this.uninstall = function() {
|
||||
global.XMLHttpRequest = realAjaxFunction;
|
||||
};
|
||||
|
||||
extend(window.FakeXMLHttpRequest.prototype, window.XMLHttpRequest);
|
||||
extend(window.FakeXMLHttpRequest.prototype, {
|
||||
requestHeaders: {},
|
||||
this.stubRequest = function(url) {
|
||||
var stub = new RequestStub(url);
|
||||
stubTracker.addStub(stub);
|
||||
return stub;
|
||||
};
|
||||
|
||||
open: function() {
|
||||
this.method = arguments[0];
|
||||
this.url = arguments[1];
|
||||
this.username = arguments[3];
|
||||
this.password = arguments[4];
|
||||
this.readyState = 1;
|
||||
},
|
||||
|
||||
setRequestHeader: function(header, value) {
|
||||
this.requestHeaders[header] = value;
|
||||
},
|
||||
|
||||
abort: function() {
|
||||
this.readyState = 0;
|
||||
},
|
||||
|
||||
readyState: 0,
|
||||
|
||||
onload: function() {
|
||||
},
|
||||
|
||||
onreadystatechange: function(isTimeout) {
|
||||
},
|
||||
|
||||
status: null,
|
||||
|
||||
send: function(data) {
|
||||
this.params = data;
|
||||
this.readyState = 2;
|
||||
|
||||
var stub = jasmine.Ajax.matchStub(this.url);
|
||||
if (stub) {
|
||||
this.response(stub);
|
||||
}
|
||||
},
|
||||
|
||||
data: function() {
|
||||
var data = {};
|
||||
if (typeof this.params !== 'string') { return data; }
|
||||
var params = this.params.split('&');
|
||||
|
||||
for (var i = 0; i < params.length; ++i) {
|
||||
var kv = params[i].replace(/\+/g, ' ').split('=');
|
||||
var key = decodeURIComponent(kv[0]);
|
||||
data[key] = data[key] || [];
|
||||
data[key].push(decodeURIComponent(kv[1]));
|
||||
data[key].sort();
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
getResponseHeader: function(name) {
|
||||
return this.responseHeaders[name];
|
||||
},
|
||||
|
||||
getAllResponseHeaders: function() {
|
||||
var responseHeaders = [];
|
||||
for (var i in this.responseHeaders) {
|
||||
if (this.responseHeaders.hasOwnProperty(i)) {
|
||||
responseHeaders.push(i + ': ' + this.responseHeaders[i]);
|
||||
}
|
||||
}
|
||||
return responseHeaders.join('\r\n');
|
||||
},
|
||||
|
||||
responseText: null,
|
||||
|
||||
response: function(response) {
|
||||
this.status = response.status;
|
||||
this.responseText = response.responseText || "";
|
||||
this.readyState = 4;
|
||||
this.responseHeaders = response.responseHeaders ||
|
||||
{"Content-type": response.contentType || "application/json" };
|
||||
|
||||
this.onload();
|
||||
this.onreadystatechange();
|
||||
},
|
||||
|
||||
responseTimeout: function() {
|
||||
this.readyState = 4;
|
||||
clock.tick(30000);
|
||||
this.onreadystatechange('timeout');
|
||||
}
|
||||
});
|
||||
|
||||
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()");
|
||||
}
|
||||
},
|
||||
|
||||
useMock: function(closure) {
|
||||
jasmine.Ajax.installMock();
|
||||
this.withMock = function(closure) {
|
||||
this.install();
|
||||
try {
|
||||
closure();
|
||||
} finally {
|
||||
jasmine.Ajax.uninstallMock();
|
||||
this.uninstall();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
installMock: function() {
|
||||
jasmine.Ajax.installTopLevel();
|
||||
jasmine.Ajax.installed = true;
|
||||
},
|
||||
this.requests = requestTracker;
|
||||
this.stubs = stubTracker;
|
||||
}
|
||||
|
||||
installTopLevel: function() {
|
||||
jasmine.Ajax.mode = 'toplevel';
|
||||
jasmine.Ajax.real = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = window.FakeXMLHttpRequest;
|
||||
},
|
||||
function StubTracker() {
|
||||
var stubs = [];
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Ajax.assertInstalled();
|
||||
window.XMLHttpRequest = jasmine.Ajax.real;
|
||||
jasmine.Ajax.reset();
|
||||
},
|
||||
this.addStub = function(stub) {
|
||||
stubs.push(stub);
|
||||
};
|
||||
|
||||
reset: function() {
|
||||
jasmine.Ajax.installed = false;
|
||||
jasmine.Ajax.mode = null;
|
||||
jasmine.Ajax.real = null;
|
||||
},
|
||||
this.reset = function() {
|
||||
stubs = [];
|
||||
};
|
||||
|
||||
stubRequest: function(url) {
|
||||
var Stub = function(url) {
|
||||
this.url = url;
|
||||
};
|
||||
|
||||
Stub.prototype.andReturn = function(options) {
|
||||
this.status = options.status || 200;
|
||||
|
||||
this.contentType = options.contentType;
|
||||
this.responseText = options.responseText;
|
||||
};
|
||||
|
||||
var stub = new Stub(url);
|
||||
|
||||
ajaxStubs.push(stub);
|
||||
|
||||
return stub;
|
||||
},
|
||||
|
||||
matchStub: function(url) {
|
||||
for (var i = ajaxStubs.length - 1; i >= 0; i--) {
|
||||
var stub = ajaxStubs[i];
|
||||
this.findStub = function(url) {
|
||||
for (var i = stubs.length - 1; i >= 0; i--) {
|
||||
var stub = stubs[i];
|
||||
if (stub.url === url) {
|
||||
return stub;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
installed: false,
|
||||
mode: null
|
||||
function fakeRequest(requestTracker, stubTracker) {
|
||||
function FakeXMLHttpRequest() {
|
||||
requestTracker.track(this);
|
||||
}
|
||||
|
||||
extend(FakeXMLHttpRequest.prototype, window.XMLHttpRequest);
|
||||
extend(FakeXMLHttpRequest.prototype, {
|
||||
requestHeaders: {},
|
||||
|
||||
};
|
||||
open: function() {
|
||||
this.method = arguments[0];
|
||||
this.url = arguments[1];
|
||||
this.username = arguments[3];
|
||||
this.password = arguments[4];
|
||||
this.readyState = 1;
|
||||
},
|
||||
|
||||
setRequestHeader: function(header, value) {
|
||||
this.requestHeaders[header] = value;
|
||||
},
|
||||
|
||||
abort: function() {
|
||||
this.readyState = 0;
|
||||
},
|
||||
|
||||
readyState: 0,
|
||||
|
||||
onload: function() {
|
||||
},
|
||||
|
||||
onreadystatechange: function(isTimeout) {
|
||||
},
|
||||
|
||||
status: null,
|
||||
|
||||
send: function(data) {
|
||||
this.params = data;
|
||||
this.readyState = 2;
|
||||
|
||||
var stub = stubTracker.findStub(this.url);
|
||||
if (stub) {
|
||||
this.response(stub);
|
||||
}
|
||||
},
|
||||
|
||||
data: function() {
|
||||
var data = {};
|
||||
if (typeof this.params !== 'string') { return data; }
|
||||
var params = this.params.split('&');
|
||||
|
||||
for (var i = 0; i < params.length; ++i) {
|
||||
var kv = params[i].replace(/\+/g, ' ').split('=');
|
||||
var key = decodeURIComponent(kv[0]);
|
||||
data[key] = data[key] || [];
|
||||
data[key].push(decodeURIComponent(kv[1]));
|
||||
data[key].sort();
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
getResponseHeader: function(name) {
|
||||
return this.responseHeaders[name];
|
||||
},
|
||||
|
||||
getAllResponseHeaders: function() {
|
||||
var responseHeaders = [];
|
||||
for (var i in this.responseHeaders) {
|
||||
if (this.responseHeaders.hasOwnProperty(i)) {
|
||||
responseHeaders.push(i + ': ' + this.responseHeaders[i]);
|
||||
}
|
||||
}
|
||||
return responseHeaders.join('\r\n');
|
||||
},
|
||||
|
||||
responseText: null,
|
||||
|
||||
response: function(response) {
|
||||
this.status = response.status;
|
||||
this.responseText = response.responseText || "";
|
||||
this.readyState = 4;
|
||||
this.responseHeaders = response.responseHeaders ||
|
||||
{"Content-type": response.contentType || "application/json" };
|
||||
|
||||
this.onload();
|
||||
this.onreadystatechange();
|
||||
},
|
||||
|
||||
responseTimeout: function() {
|
||||
this.readyState = 4;
|
||||
clock.tick(30000);
|
||||
this.onreadystatechange('timeout');
|
||||
}
|
||||
});
|
||||
|
||||
return FakeXMLHttpRequest;
|
||||
}
|
||||
|
||||
function RequestTracker() {
|
||||
var requests = [];
|
||||
|
||||
this.track = function(request) {
|
||||
requests.push(request);
|
||||
};
|
||||
|
||||
this.first = function() {
|
||||
return requests[0];
|
||||
};
|
||||
|
||||
this.count = function() {
|
||||
return requests.length;
|
||||
};
|
||||
|
||||
this.reset = function() {
|
||||
requests = [];
|
||||
};
|
||||
|
||||
this.mostRecent = function() {
|
||||
return requests[requests.length - 1];
|
||||
};
|
||||
}
|
||||
|
||||
function RequestStub(url) {
|
||||
this.url = url;
|
||||
|
||||
this.andReturn = function(options) {
|
||||
this.status = options.status || 200;
|
||||
|
||||
this.contentType = options.contentType;
|
||||
this.responseText = options.responseText;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window === "undefined" && typeof exports === "object") {
|
||||
exports.MockAjax = MockAjax;
|
||||
} else {
|
||||
window.MockAjax = MockAjax;
|
||||
}
|
||||
}());
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
describe("FakeXMLHttpRequest", function() {
|
||||
var xhr;
|
||||
beforeEach(function() {
|
||||
xhr = new FakeXMLHttpRequest();
|
||||
var realXMLHttpRequest = jasmine.createSpy('realRequest'),
|
||||
fakeGlobal = {XMLHttpRequest: realXMLHttpRequest},
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
mockAjax.install();
|
||||
xhr = new fakeGlobal.XMLHttpRequest();
|
||||
});
|
||||
|
||||
it("should have an initial readyState of 0 (uninitialized)", function() {
|
||||
expect(xhr.readyState).toEqual(0);
|
||||
});
|
||||
@ -52,6 +57,7 @@ describe("FakeXMLHttpRequest", function() {
|
||||
});
|
||||
|
||||
it("can be extended", function(){
|
||||
pending("why do we want to do this?");
|
||||
FakeXMLHttpRequest.prototype.foo = function(){
|
||||
return "foo";
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
beforeEach(function() {
|
||||
clearAjaxRequests();
|
||||
});
|
||||
// beforeEach(function() {
|
||||
// clearAjaxRequests();
|
||||
// });
|
||||
|
@ -1,116 +1,52 @@
|
||||
describe("jasmine.Ajax", function() {
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.reset();
|
||||
describe("mockAjax", function() {
|
||||
it("does not replace XMLHttpRequest until it is installed", function() {
|
||||
var fakeXmlHttpRequest = jasmine.createSpy('fakeXmlHttpRequest'),
|
||||
fakeGlobal = { XMLHttpRequest: fakeXmlHttpRequest },
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
fakeGlobal.XMLHttpRequest('foo');
|
||||
expect(fakeXmlHttpRequest).toHaveBeenCalledWith('foo');
|
||||
fakeXmlHttpRequest.calls.reset();
|
||||
|
||||
mockAjax.install();
|
||||
fakeGlobal.XMLHttpRequest('foo');
|
||||
expect(fakeXmlHttpRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("isInstalled", function() {
|
||||
it("returns true if the mock has been installed", function() {
|
||||
jasmine.Ajax.installed = true;
|
||||
expect(jasmine.Ajax.isInstalled()).toBeTruthy();
|
||||
});
|
||||
it("replaces the global XMLHttpRequest on uninstall", function() {
|
||||
var fakeXmlHttpRequest = jasmine.createSpy('fakeXmlHttpRequest'),
|
||||
fakeGlobal = { XMLHttpRequest: fakeXmlHttpRequest },
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
it("returns false if the mock has not been installed", function() {
|
||||
jasmine.Ajax.installed = false;
|
||||
expect(jasmine.Ajax.isInstalled()).toBeFalsy();
|
||||
});
|
||||
mockAjax.install();
|
||||
mockAjax.uninstall();
|
||||
|
||||
fakeGlobal.XMLHttpRequest('foo');
|
||||
expect(fakeXmlHttpRequest).toHaveBeenCalledWith('foo');
|
||||
});
|
||||
|
||||
describe("assertInstalled", function() {
|
||||
it("doesn't raise an error if the mock is installed", function() {
|
||||
jasmine.Ajax.installed = true;
|
||||
expect(
|
||||
function() {
|
||||
jasmine.Ajax.assertInstalled();
|
||||
}).not.toThrowError("Mock ajax is not installed, use jasmine.Ajax.useMock()");
|
||||
});
|
||||
it("allows the httpRequest to be retrieved", function() {
|
||||
var fakeXmlHttpRequest = jasmine.createSpy('fakeXmlHttpRequest'),
|
||||
fakeGlobal = { XMLHttpRequest: fakeXmlHttpRequest },
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
it("raises an error if the mock is not installed", function() {
|
||||
jasmine.Ajax.installed = false;
|
||||
expect(
|
||||
function() {
|
||||
jasmine.Ajax.assertInstalled();
|
||||
}).toThrowError("Mock ajax is not installed, use jasmine.Ajax.useMock()");
|
||||
});
|
||||
mockAjax.install();
|
||||
var request = new fakeGlobal.XMLHttpRequest();
|
||||
|
||||
expect(mockAjax.requests.count()).toBe(1);
|
||||
expect(mockAjax.requests.mostRecent()).toBe(request);
|
||||
});
|
||||
|
||||
describe("installMock", function() {
|
||||
describe("when using a top-level replacement", function() {
|
||||
it("allows the httpRequests to be cleared", function() {
|
||||
var fakeXmlHttpRequest = jasmine.createSpy('fakeXmlHttpRequest'),
|
||||
fakeGlobal = { XMLHttpRequest: fakeXmlHttpRequest },
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
it("installs the mock", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
expect(window.XMLHttpRequest).toBe(FakeXMLHttpRequest);
|
||||
});
|
||||
|
||||
it("saves a reference to the browser's XHR", function() {
|
||||
var xhr = window.XMLHttpRequest;
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jasmine.Ajax.real).toBe(xhr);
|
||||
});
|
||||
|
||||
it("sets mode to 'toplevel'", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jasmine.Ajax.mode).toEqual("toplevel");
|
||||
});
|
||||
});
|
||||
|
||||
it("sets the installed flag to true", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
expect(jasmine.Ajax.installed).toBeTruthy();
|
||||
});
|
||||
mockAjax.install();
|
||||
var request = new fakeGlobal.XMLHttpRequest();
|
||||
|
||||
expect(mockAjax.requests.mostRecent()).toBe(request);
|
||||
mockAjax.requests.reset();
|
||||
expect(mockAjax.requests.count()).toBe(0);
|
||||
});
|
||||
|
||||
describe("uninstallMock", function() {
|
||||
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(window.XMLHttpRequest).toBe(xhr);
|
||||
});
|
||||
});
|
||||
|
||||
it("raises an exception if jasmine.Ajax is not installed", function() {
|
||||
expect(function(){ jasmine.Ajax.uninstallMock(); }).toThrowError("Mock ajax is not installed, use jasmine.Ajax.useMock()");
|
||||
});
|
||||
|
||||
it("sets the installed flag to false", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
jasmine.Ajax.uninstallMock();
|
||||
expect(jasmine.Ajax.installed).toBeFalsy();
|
||||
|
||||
// so uninstallMock doesn't throw error when spec.after runs
|
||||
jasmine.Ajax.installMock();
|
||||
});
|
||||
|
||||
it("sets the mode to null", function() {
|
||||
jasmine.Ajax.installMock();
|
||||
jasmine.Ajax.uninstallMock();
|
||||
expect(jasmine.Ajax.mode).toEqual(null);
|
||||
jasmine.Ajax.installMock();
|
||||
});
|
||||
});
|
||||
|
||||
describe("useMock", function() {
|
||||
it("installs the mock and uninstalls when done", function() {
|
||||
var realRequest = spyOn(window, 'XMLHttpRequest'),
|
||||
fakeRequest = spyOn(window, 'FakeXMLHttpRequest');
|
||||
expect(function() {
|
||||
jasmine.Ajax.useMock(function() {
|
||||
window.XMLHttpRequest();
|
||||
throw "function that has an error"
|
||||
});
|
||||
}).toThrow();
|
||||
expect(realRequest).not.toHaveBeenCalled();
|
||||
expect(fakeRequest).toHaveBeenCalled();
|
||||
fakeRequest.calls.reset();
|
||||
window.XMLHttpRequest();
|
||||
expect(realRequest).toHaveBeenCalled();
|
||||
expect(fakeRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -3,9 +3,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
var success, error, complete;
|
||||
var client, onreadystatechange;
|
||||
var sharedContext = {};
|
||||
var fakeGlobal, mockAjax;
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.installMock();
|
||||
var fakeXMLHttpRequest = jasmine.createSpy('realFakeXMLHttpRequest');
|
||||
fakeGlobal = {XMLHttpRequest: fakeXMLHttpRequest};
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
mockAjax.install();
|
||||
|
||||
success = jasmine.createSpy("onSuccess");
|
||||
error = jasmine.createSpy("onFailure");
|
||||
@ -29,17 +33,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.Ajax.uninstallMock();
|
||||
});
|
||||
|
||||
describe("when making a request", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.send();
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
});
|
||||
|
||||
it("should store URL and transport", function() {
|
||||
@ -47,73 +47,74 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
});
|
||||
|
||||
it("should queue the request", function() {
|
||||
expect(ajaxRequests.length).toEqual(1);
|
||||
expect(mockAjax.requests.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it("should allow access to the queued request", function() {
|
||||
expect(ajaxRequests[0]).toEqual(request);
|
||||
expect(mockAjax.requests.first()).toEqual(request);
|
||||
});
|
||||
|
||||
describe("and then another request", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.send();
|
||||
|
||||
anotherRequest = mostRecentAjaxRequest();
|
||||
anotherRequest = mockAjax.requests.mostRecent();
|
||||
});
|
||||
|
||||
it("should queue the next request", function() {
|
||||
expect(ajaxRequests.length).toEqual(2);
|
||||
expect(mockAjax.requests.count()).toEqual(2);
|
||||
});
|
||||
|
||||
it("should allow access to the other queued request", function() {
|
||||
expect(ajaxRequests[1]).toEqual(anotherRequest);
|
||||
expect(mockAjax.requests.first()).toEqual(request);
|
||||
expect(mockAjax.requests.mostRecent()).toEqual(anotherRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mostRecentAjaxRequest", function () {
|
||||
describe("mockAjax.requests.mostRecent()", function () {
|
||||
|
||||
describe("when there is one request queued", function () {
|
||||
it("should return the request", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(request);
|
||||
expect(mockAjax.requests.mostRecent()).toEqual(request);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there is more than one request", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.send();
|
||||
anotherRequest = mostRecentAjaxRequest();
|
||||
anotherRequest = mockAjax.requests.mostRecent();
|
||||
});
|
||||
|
||||
it("should return the most recent request", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(anotherRequest);
|
||||
expect(mockAjax.requests.mostRecent()).toEqual(anotherRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there are no requests", function () {
|
||||
beforeEach(function() {
|
||||
clearAjaxRequests();
|
||||
mockAjax.requests.reset();
|
||||
});
|
||||
|
||||
it("should return null", function() {
|
||||
expect(mostRecentAjaxRequest()).toEqual(null);
|
||||
expect(mockAjax.requests.mostRecent()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearAjaxRequests()", function () {
|
||||
beforeEach(function() {
|
||||
clearAjaxRequests();
|
||||
mockAjax.requests.reset();
|
||||
});
|
||||
|
||||
it("should remove all requests", function() {
|
||||
expect(ajaxRequests.length).toEqual(0);
|
||||
expect(mostRecentAjaxRequest()).toEqual(null);
|
||||
expect(mockAjax.requests.count()).toEqual(0);
|
||||
expect(mockAjax.requests.mostRecent()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -121,13 +122,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
describe("when simulating a response with request.response", function () {
|
||||
describe("and the response is Success", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "text/plain")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
response = {status: 200, contentType: "text/html", responseText: "OK!"};
|
||||
request.response(response);
|
||||
|
||||
@ -154,13 +155,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
|
||||
describe("and the response is Success, but with JSON", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "application/json")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
var responseObject = {status: 200, contentType: "application/json", responseText: '{"foo":"bar"}'};
|
||||
|
||||
request.response(responseObject);
|
||||
@ -194,13 +195,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
|
||||
describe("the content type defaults to application/json", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "application/json")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
response = {status: 200, responseText: '{"foo": "valid JSON, dammit."}'};
|
||||
request.response(response);
|
||||
|
||||
@ -227,13 +228,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
|
||||
describe("and the status/response code is 0", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "text/plain")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
response = {status: 0, responseText: '{"foo": "whoops!"}'};
|
||||
request.response(response);
|
||||
|
||||
@ -261,13 +262,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
|
||||
describe("and the response is error", function () {
|
||||
beforeEach(function() {
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "text/plain")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
response = {status: 500, contentType: "text/html", responseText: "(._){"};
|
||||
request.response(response);
|
||||
|
||||
@ -296,13 +297,13 @@ describe("Jasmine Mock Ajax (for toplevel)", function() {
|
||||
beforeEach(function() {
|
||||
clock.install();
|
||||
|
||||
client = new XMLHttpRequest();
|
||||
client = new fakeGlobal.XMLHttpRequest();
|
||||
client.onreadystatechange = onreadystatechange;
|
||||
client.open("GET", "example.com/someApi");
|
||||
client.setRequestHeader("Content-Type", "text/plain")
|
||||
client.send();
|
||||
|
||||
request = mostRecentAjaxRequest();
|
||||
request = mockAjax.requests.mostRecent();
|
||||
response = {contentType: "text/html", responseText: "(._){"};
|
||||
request.responseTimeout(response);
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
describe("Webmock style mocking", function() {
|
||||
var successSpy, errorSpy, response;
|
||||
var successSpy, errorSpy, response, fakeGlobal, mockAjax;
|
||||
|
||||
var sendRequest = function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var sendRequest = function(fakeGlobal) {
|
||||
var xhr = new fakeGlobal.XMLHttpRequest();
|
||||
xhr.onreadystatechange = function(arguments) {
|
||||
if (this.readyState == this.DONE) {
|
||||
response = this;
|
||||
successSpy();
|
||||
}
|
||||
};
|
||||
|
||||
@ -14,47 +15,44 @@ describe("Webmock style mocking", function() {
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.installMock();
|
||||
jasmine.Ajax.stubRequest("http://example.com/someApi").andReturn({responseText: "hi!"});
|
||||
successSpy = jasmine.createSpy('success');
|
||||
fakeGlobal = {XMLHttpRequest: jasmine.createSpy('realXMLHttpRequest')};
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
mockAjax.install();
|
||||
|
||||
sendRequest();
|
||||
mockAjax.stubRequest("http://example.com/someApi").andReturn({responseText: "hi!"});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.Ajax.uninstallMock();
|
||||
clearAjaxStubs();
|
||||
it("allows a url to be setup as a stub", function() {
|
||||
sendRequest(fakeGlobal);
|
||||
expect(successSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should allow you to clear all the ajax stubs", function() {
|
||||
expect(ajaxStubs.length).toEqual(1);
|
||||
clearAjaxStubs();
|
||||
expect(ajaxStubs.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("should push the new stub on the ajaxStubs", function() {
|
||||
expect(ajaxStubs.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("should set the url in the stub", function() {
|
||||
expect(ajaxStubs[0].url).toEqual("http://example.com/someApi");
|
||||
mockAjax.stubs.reset();
|
||||
sendRequest(fakeGlobal);
|
||||
expect(successSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should set the contentType", function() {
|
||||
sendRequest(fakeGlobal);
|
||||
expect(response.responseHeaders['Content-type']).toEqual('application/json');
|
||||
});
|
||||
|
||||
it("should set the responseText", function() {
|
||||
sendRequest(fakeGlobal);
|
||||
expect(response.responseText).toEqual('hi!');
|
||||
});
|
||||
|
||||
it("should default the status to 200", function() {
|
||||
sendRequest(fakeGlobal);
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
|
||||
describe("with another stub for the same url", function() {
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.stubRequest("http://example.com/someApi").andReturn({responseText: "no", status: 403});
|
||||
sendRequest();
|
||||
mockAjax.stubRequest("http://example.com/someApi").andReturn({responseText: "no", status: 403});
|
||||
sendRequest(fakeGlobal);
|
||||
});
|
||||
|
||||
it("should set the status", function() {
|
||||
@ -65,25 +63,4 @@ describe("Webmock style mocking", function() {
|
||||
expect(response.responseText).toEqual('no');
|
||||
});
|
||||
});
|
||||
|
||||
describe(".matchStub", function() {
|
||||
it("should be able to find a stub with an exact match", function() {
|
||||
var stub = jasmine.Ajax.matchStub("http://example.com/someApi");
|
||||
|
||||
expect(stub).toBeDefined();
|
||||
});
|
||||
|
||||
describe("with another stub for the same url", function() {
|
||||
beforeEach(function() {
|
||||
jasmine.Ajax.stubRequest("http://example.com/someApi").andReturn({responseText: "no", status: 403});
|
||||
});
|
||||
|
||||
it("should use the latest stub", function() {
|
||||
var stub = jasmine.Ajax.matchStub("http://example.com/someApi");
|
||||
|
||||
expect(stub.status).toEqual(403);
|
||||
expect(stub.responseText).toEqual('no');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
37
spec/javascripts/with-mock-spec.js
Normal file
37
spec/javascripts/with-mock-spec.js
Normal file
@ -0,0 +1,37 @@
|
||||
describe("withMock", function() {
|
||||
var sendRequest = function(fakeGlobal) {
|
||||
var xhr = new fakeGlobal.XMLHttpRequest();
|
||||
|
||||
xhr.open("GET", "http://example.com/someApi");
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
it("installs the mock for passed in function, and uninstalls when complete", function() {
|
||||
var xmlHttpRequest = spyOn(window, 'XMLHttpRequest').and.returnValue({open: function() {}, send: function() {}}),
|
||||
fakeGlobal = {XMLHttpRequest: xmlHttpRequest},
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
mockAjax.withMock(function() {
|
||||
sendRequest(fakeGlobal);
|
||||
expect(xmlHttpRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
sendRequest(fakeGlobal);
|
||||
expect(xmlHttpRequest).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("properly uninstalls when the passed in function throws", function() {
|
||||
var xmlHttpRequest = spyOn(window, 'XMLHttpRequest').and.returnValue({open: function() {}, send: function() {}}),
|
||||
fakeGlobal = {XMLHttpRequest: xmlHttpRequest},
|
||||
mockAjax = new MockAjax(fakeGlobal);
|
||||
|
||||
expect(function() {
|
||||
mockAjax.withMock(function() {
|
||||
throw "error"
|
||||
});
|
||||
}).toThrow("error");
|
||||
|
||||
sendRequest(fakeGlobal);
|
||||
expect(xmlHttpRequest).toHaveBeenCalled();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user