/** * @depend ../../sinon.js * @depend event.js */ /*jslint eqeqeq: false, onevar: false*/ /*global sinon, module, require, XDomainRequest*/ /** * Fake XDomainRequest object */ "use strict"; if (typeof sinon == "undefined") { this.sinon = {}; } sinon.xdr = { XDomainRequest: this.XDomainRequest }; // wrapper for global (function (global) { var xdr = sinon.xdr; xdr.GlobalXDomainRequest = global.XDomainRequest; xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined"; xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false; function FakeXDomainRequest() { this.readyState = FakeXDomainRequest.UNSENT; this.requestBody = null; this.requestHeaders = {}; this.status = 0; this.timeout = null; if (typeof FakeXDomainRequest.onCreate == "function") { FakeXDomainRequest.onCreate(this); } } function verifyState(xdr) { if (xdr.readyState !== FakeXDomainRequest.OPENED) { throw new Error("INVALID_STATE_ERR"); } if (xdr.sendFlag) { throw new Error("INVALID_STATE_ERR"); } } function verifyRequestSent(xdr) { if (xdr.readyState == FakeXDomainRequest.UNSENT) { throw new Error("Request not sent"); } if (xdr.readyState == FakeXDomainRequest.DONE) { throw new Error("Request done"); } } function verifyResponseBodyType(body) { if (typeof body != "string") { var error = new Error("Attempted to respond to fake XDomainRequest with " + body + ", which is not a string."); error.name = "InvalidBodyException"; throw error; } } sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, { open: function open(method, url) { this.method = method; this.url = url; this.responseText = null; this.sendFlag = false; this.readyStateChange(FakeXDomainRequest.OPENED); }, readyStateChange: function readyStateChange(state) { this.readyState = state; var eventName = ''; switch (this.readyState) { case FakeXDomainRequest.UNSENT: break; case FakeXDomainRequest.OPENED: break; case FakeXDomainRequest.LOADING: if (this.sendFlag){ //raise the progress event eventName = 'onprogress'; } break; case FakeXDomainRequest.DONE: if (this.isTimeout){ eventName = 'ontimeout' } else if (this.errorFlag || (this.status < 200 || this.status > 299)) { eventName = 'onerror'; } else { eventName = 'onload' } break; } // raising event (if defined) if (eventName) { if (typeof this[eventName] == "function") { try { this[eventName](); } catch (e) { sinon.logError("Fake XHR " + eventName + " handler", e); } } } }, send: function send(data) { verifyState(this); if (!/^(get|head)$/i.test(this.method)) { this.requestBody = data; } this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8"; this.errorFlag = false; this.sendFlag = true; this.readyStateChange(FakeXDomainRequest.OPENED); if (typeof this.onSend == "function") { this.onSend(this); } }, abort: function abort() { this.aborted = true; this.responseText = null; this.errorFlag = true; if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) { this.readyStateChange(sinon.FakeXDomainRequest.DONE); this.sendFlag = false; } }, setResponseBody: function setResponseBody(body) { verifyRequestSent(this); verifyResponseBodyType(body); var chunkSize = this.chunkSize || 10; var index = 0; this.responseText = ""; do { this.readyStateChange(FakeXDomainRequest.LOADING); this.responseText += body.substring(index, index + chunkSize); index += chunkSize; } while (index < body.length); this.readyStateChange(FakeXDomainRequest.DONE); }, respond: function respond(status, contentType, body) { // content-type ignored, since XDomainRequest does not carry this // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease // test integration across browsers this.status = typeof status == "number" ? status : 200; this.setResponseBody(body || ""); }, simulatetimeout: function(){ this.status = 0; this.isTimeout = true; // Access to this should actually throw an error this.responseText = undefined; this.readyStateChange(FakeXDomainRequest.DONE); } }); sinon.extend(FakeXDomainRequest, { UNSENT: 0, OPENED: 1, LOADING: 3, DONE: 4 }); sinon.useFakeXDomainRequest = function () { sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) { if (xdr.supportsXDR) { global.XDomainRequest = xdr.GlobalXDomainRequest; } delete sinon.FakeXDomainRequest.restore; if (keepOnCreate !== true) { delete sinon.FakeXDomainRequest.onCreate; } }; if (xdr.supportsXDR) { global.XDomainRequest = sinon.FakeXDomainRequest; } return sinon.FakeXDomainRequest; }; sinon.FakeXDomainRequest = FakeXDomainRequest; })(this); if (typeof module == "object" && typeof require == "function") { module.exports = sinon; }