// JSpec - XHR - Copyright TJ Holowaychuk (MIT Licensed) (function(){ // --- Original XMLHttpRequest var OriginalXMLHttpRequest = 'XMLHttpRequest' in this ? XMLHttpRequest : function(){} // --- MockXMLHttpRequest var MockXMLHttpRequest = function() { this.requestHeaders = {} } MockXMLHttpRequest.prototype = { status : 0, async : true, readyState : 0, responseText : '', abort : function(){}, onreadystatechange : function(){}, /** * Return response headers hash. */ getAllResponseHeaders : function(){ return this.responseHeaders }, /** * Return case-insensitive value for header _name_. */ getResponseHeader : function(name) { return this.responseHeaders[name.toLowerCase()] }, /** * Set case-insensitive _value_ for header _name_. */ setRequestHeader : function(name, value) { this.requestHeaders[name.toLowerCase()] = value }, /** * Open mock request. */ open : function(method, url, async, user, password) { this.user = user this.password = password this.url = url this.readyState = 1 this.method = method.toUpperCase() if (async != undefined) this.async = async if (this.async) this.onreadystatechange() }, /** * Send request _data_. */ send : function(data) { this.data = data this.readyState = 4 if (this.method == 'HEAD') this.responseText = null this.responseHeaders['content-length'] = (this.responseText || '').length if(this.async) this.onreadystatechange() } } // --- Response status codes JSpec.statusCodes = { 100 : 'Continue', 101 : 'Switching Protocols', 200 : 'OK', 201 : 'Created', 202 : 'Accepted', 203 : 'Non-Authoritative Information', 204 : 'No Content', 205 : 'Reset Content', 206 : 'Partial Content', 300 : 'Multiple Choice', 301 : 'Moved Permanently', 302 : 'Found', 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 Timeout', 409 : 'Conflict', 410 : 'Gone', 411 : 'Length Required', 412 : 'Precondition Failed', 413 : 'Request Entity Too Large', 414 : 'Request-URI Too Long', 415 : 'Unsupported Media Type', 416 : 'Requested Range Not Satisfiable', 417 : 'Expectation Failed', 422 : 'Unprocessable Entity', 500 : 'Internal Server Error', 501 : 'Not Implemented', 502 : 'Bad Gateway', 503 : 'Service Unavailable', 504 : 'Gateway Timeout', 505 : 'HTTP Version Not Supported' } /** * Mock XMLHttpRequest requests. * * mockRequest().and_return('some data', 'text/plain', 200, { 'X-SomeHeader' : 'somevalue' }) * * @return {hash} * @api public */ function mockRequest() { return { and_return : function(body, type, status, headers) { XMLHttpRequest = MockXMLHttpRequest status = status || 200 headers = headers || {} headers['content-type'] = type JSpec.extend(XMLHttpRequest.prototype, { responseText : body, responseHeaders : headers, status : status, statusText : JSpec.statusCodes[status] }) }} } /** * Unmock XMLHttpRequest requests. * * @api public */ function unmockRequest() { XMLHttpRequest = OriginalXMLHttpRequest } JSpec.include({ // --- Utilities utilities : { mockRequest : mockRequest, unmockRequest : unmockRequest }, // --- Hooks afterSpec : function() { this.utilities.unmockRequest() } }) })()