Last active
February 15, 2016 15:13
-
-
Save Seteh/5a3c5386b7e0a1772ccb to your computer and use it in GitHub Desktop.
A tool for mocking XMLHttpRequest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(global) { | |
var DummyServer = function() { | |
var states = { | |
UNSENT: 0, | |
OPENED: 1, | |
HEADERS_RECEIVED: 2, | |
LOADING: 3, | |
DONE: 4 | |
}; | |
var statuses = function() { | |
// NOTE: function as #region | |
return { | |
100: 'Continue', | |
101: 'Switching Protocols', | |
102: 'Processing', | |
200: 'OK', | |
201: 'Created', | |
202: 'Accepted', | |
203: 'Non-Authoritative Information', | |
204: 'No Content', | |
205: 'Reset Content', | |
206: 'Partial Content', | |
207: 'Multi-Status', | |
300: 'Multiple Choices', | |
301: 'Moved Permanently', | |
302: 'Moved Temporarily', | |
303: 'See Other', | |
304: 'Not Modified', | |
305: 'Use Proxy', | |
307: 'Temporary Redirect', | |
400: 'Bad Request', | |
401: 'Unauthorized', | |
402: 'Payment Required', | |
403: 'Forbidden', | |
404: 'Not Found', | |
405: 'Method Not Allowed', | |
406: 'Not Acceptable', | |
407: 'Proxy Authentication Required', | |
408: 'Request Time-out', | |
409: 'Conflict', | |
410: 'Gone', | |
411: 'Length Required', | |
412: 'Precondition Failed', | |
413: 'Request Entity Too Large', | |
414: 'Request-URI Too Large', | |
415: 'Unsupported Media Type', | |
416: 'Requested range not satisfiable', | |
417: 'Expectation Failed', | |
422: 'Unprocessable Entity', | |
423: 'Locked', | |
424: 'Failed Dependency', | |
500: 'Internal Server Error', | |
501: 'Not Implemented', | |
502: 'Bad Gateway', | |
503: 'Service Unavailable', | |
504: 'Gateway Time-out', | |
505: 'HTTP Version not supported', | |
507: 'Insufficient Storage' | |
}; | |
}(); | |
function openXhr(xhr) { | |
xhr.readyState = states.OPENED; | |
xhr.onreadystatechange(); | |
} | |
function sendXhr(xhr) { | |
xhr.sent = true; | |
xhr.onreadystatechange(); | |
xhr.onsend(); | |
DummyServer.handle(xhr); | |
} | |
function abortXhr(xhr) { | |
xhr.error = true; | |
xhr.onreadystatechange(); | |
xhr.onabort(); | |
xhr.readyState = states.UNSENT; | |
} | |
function recieveXhr(xhr) { | |
var key, | |
status = xhr.response.status || 200, | |
headers = xhr.response.headers || {}, | |
responseText = xhr.response.responseText || ""; | |
for(key in headers) if(headers.hasOwnProperty(key)) | |
xhr.responseHeaders[key] = headers[key]; | |
xhr.status = status; | |
xhr.statusText = status + " " + statuses[status]; | |
xhr.readyState = states.HEADERS_RECEIVED; | |
xhr.onprogress(); | |
xhr.onreadystatechange(); | |
xhr.responseText = responseText; | |
xhr.readyState = states.LOADING; | |
xhr.onprogress(); | |
xhr.onreadystatechange(); | |
xhr.readyState = states.DONE; | |
xhr.onreadystatechange(); | |
xhr.onprogress(); | |
xhr.onload(); | |
} | |
var DummyServer = function() { | |
var queue = null; | |
var originalXhr = null; | |
function on() { | |
return queue !== null; | |
} | |
function setup() { | |
if(on()) | |
throw new Error("Can't be setuped twice."); | |
queue = []; | |
originalXhr = XMLHttpRequest; | |
global.XMLHttpRequest = DummyXMLHttpRequest; | |
} | |
function teardown() { | |
if(!on()) | |
throw new Error("Teardown before setup."); | |
global.XMLHttpRequest = originalXhr; | |
originalXhr = null; | |
queue = null; | |
} | |
function handle(xhr) { | |
var cb; | |
if(queue.length) { | |
cb = queue.shift(); | |
if(cb(xhr) === false) { | |
abortXhr(xhr); | |
return; | |
} | |
} | |
recieveXhr(xhr); | |
} | |
function enqueue(cb) { | |
queue.push(cb); | |
} | |
return { | |
setup: setup, | |
handle: handle, | |
enqueue: enqueue, | |
teardown: teardown | |
}; | |
}(); | |
function DummyXMLHttpRequest() { | |
this.onsend = function() { }; | |
this.onload = function() { }; | |
this.onabort = function() { }; | |
this.onprogress = function() { }; | |
this.onreadystatechange = function() { }; | |
this.withCredentials = false; | |
} | |
DummyXMLHttpRequest.prototype = { | |
constructor: DummyXMLHttpRequest, | |
open: function(method, URL, async, userName, password) { | |
this.url = URL; | |
this.async = async || true; | |
this.method = method.toUpperCase(); | |
this.userName = userName; | |
this.password = password; | |
this.readyState = -1; | |
this.error = false; | |
this.sent = false; | |
this.requestHeaders = {}; | |
this.responseHeaders = {}; | |
openXhr(this); | |
}, | |
send: function(content) { | |
this.requestText = String(content); | |
sendXhr(this); | |
}, | |
abort: function() { | |
this.responseText = ""; | |
this.requestText = null; | |
abortXhr(this); | |
}, | |
setRequestHeader: function(label, value) { | |
if(!this.requestHeaders[label]) | |
this.requestHeaders[label] = value; | |
else this.requestHeaders[label] = this.requestHeaders[label] + ", " + value; | |
}, | |
getAllResponseHeaders: function() { | |
var headers = [], | |
headerName; | |
if(this.error) | |
return null; | |
if(this.readyState === states.UNSENT || this.readyState === states.OPENED) | |
throw new Error("INVALID_STATE_ERR"); | |
for(headerName in this.responseHeaders) | |
headers.push(headerName.charAt(0).toUpperCase() + headerName.substr(1) + ":" + this.responseHeaders[headerName]); | |
return headers.join("\r\n"); | |
}, | |
getResponseHeader: function(headerName) { | |
if(this.error) | |
return null; | |
if(this.readyState === states.UNSENT || this.readyState === states.OPENED) | |
throw new Error("INVALID_STATE_ERR"); | |
return this.responseHeaders[headerName.toLowerCase()]; | |
}, | |
overrideMimeType: function(mimeType) { }, | |
setResponse: function(response) { | |
this.response = response; | |
} | |
}; | |
return { | |
setup: function() { | |
DummyServer.setup(); | |
}, | |
enqueue: function(cb) { | |
DummyServer.enqueue(cb); | |
}, | |
teardown: function() { | |
DummyServer.teardown(); | |
} | |
}; | |
}(); | |
global.DummyServer = DummyServer; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment