sku-pg
Version:
Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!
473 lines (388 loc) • 13.4 kB
JavaScript
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock of XhrIo for unit testing.
*
*
*/
goog.provide('goog.testing.net.XhrIo');
goog.require('goog.array');
goog.require('goog.dom.xml');
goog.require('goog.events');
goog.require('goog.events.EventTarget');
goog.require('goog.json');
goog.require('goog.net.ErrorCode');
goog.require('goog.net.EventType');
goog.require('goog.net.XmlHttp');
goog.require('goog.structs.Map');
/**
* Mock implementation of goog.net.XhrIo. This doesn't provide a mock
* implementation for all cases, but it's not too hard to add them as needed.
* @param {goog.testing.TestQueue=} opt_testQueue Test queue for inserting test
* events.
* @constructor
* @extends {goog.events.EventTarget}
*/
goog.testing.net.XhrIo = function(opt_testQueue) {
goog.events.EventTarget.call(this);
/**
* Map of default headers to add to every request, use:
* XhrIo.headers.set(name, value)
* @type {goog.structs.Map}
*/
this.headers = new goog.structs.Map();
/**
* Queue of events write to.
* @type {goog.testing.TestQueue?}
* @private
*/
this.testQueue_ = opt_testQueue || null;
};
goog.inherits(goog.testing.net.XhrIo, goog.events.EventTarget);
/**
* All non-disposed instances of goog.testing.net.XhrIo created
* by {@link goog.testing.net.XhrIo.send} are in this Array.
* @see goog.testing.net.XhrIo.cleanupAllPendingStaticSends
* @type {Array.<goog.testing.net.XhrIo>}
* @private
*/
goog.testing.net.XhrIo.sendInstances_ = [];
/**
* Returns an Array containing all non-disposed instances of
* goog.testing.net.XhrIo created by {@link goog.testing.net.XhrIo.send}.
* @return {Array} Array of goog.testing.net.XhrIo instances.
*/
goog.testing.net.XhrIo.getSendInstances = function() {
return goog.testing.net.XhrIo.sendInstances_;
};
/**
* Simulates the static XhrIo send method.
* @param {string} url Uri to make request to.
* @param {Function=} opt_callback Callback function for when request is
* complete.
* @param {string=} opt_method Send method, default: GET.
* @param {string=} opt_content Post data.
* @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
* request.
* @param {number=} opt_timeoutInterval Number of milliseconds after which an
* incomplete request will be aborted; 0 means no timeout is set.
*/
goog.testing.net.XhrIo.send = function(url, opt_callback, opt_method,
opt_content, opt_headers,
opt_timeoutInterval) {
var x = new goog.testing.net.XhrIo();
goog.testing.net.XhrIo.sendInstances_.push(x);
if (opt_callback) {
goog.events.listen(x, goog.net.EventType.COMPLETE, opt_callback);
}
goog.events.listen(x,
goog.net.EventType.READY,
goog.partial(goog.testing.net.XhrIo.cleanupSend_, x));
if (opt_timeoutInterval) {
x.setTimeoutInterval(opt_timeoutInterval);
}
x.send(url, opt_method, opt_content, opt_headers);
};
/**
* Disposes of the specified goog.testing.net.XhrIo created by
* {@link goog.testing.net.XhrIo.send} and removes it from
* {@link goog.testing.net.XhrIo.pendingStaticSendInstances_}.
* @param {goog.testing.net.XhrIo} XhrIo An XhrIo created by
* {@link goog.testing.net.XhrIo.send}.
* @private
*/
goog.testing.net.XhrIo.cleanupSend_ = function(XhrIo) {
XhrIo.dispose();
goog.array.remove(goog.testing.net.XhrIo.sendInstances_, XhrIo);
};
/**
* Stores the simulated response headers for the requests which are sent through
* this XhrIo.
* @type {Object}
* @private
*/
goog.testing.net.XhrIo.prototype.responseHeaders_;
/**
* Whether MockXhrIo is active.
* @type {boolean}
* @private
*/
goog.testing.net.XhrIo.prototype.active_ = false;
/**
* Last URI that was requested.
* @type {string}
* @private
*/
goog.testing.net.XhrIo.prototype.lastUri_ = '';
/**
* Last error code.
* @type {goog.net.ErrorCode}
* @private
*/
goog.testing.net.XhrIo.prototype.lastErrorCode_ =
goog.net.ErrorCode.NO_ERROR;
/**
* Last error message.
* @type {string}
* @private
*/
goog.testing.net.XhrIo.prototype.lastError_ = '';
/**
* Mock ready state.
* @type {number}
* @private
*/
goog.testing.net.XhrIo.prototype.readyState_ =
goog.net.XmlHttp.ReadyState.UNINITIALIZED;
/**
* Number of milliseconds after which an incomplete request will be aborted and
* a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout is set.
* @type {number}
* @private
*/
goog.testing.net.XhrIo.prototype.timeoutInterval_ = 0;
/**
* Window timeout ID used to cancel the timeout event handler if the request
* completes successfully.
* @type {Object}
* @private
*/
goog.testing.net.XhrIo.prototype.timeoutId_ = null;
/**
* Returns the number of milliseconds after which an incomplete request will be
* aborted, or 0 if no timeout is set.
* @return {number} Timeout interval in milliseconds.
*/
goog.testing.net.XhrIo.prototype.getTimeoutInterval = function() {
return this.timeoutInterval_;
};
/**
* Sets the number of milliseconds after which an incomplete request will be
* aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no
* timeout is set.
* @param {number} ms Timeout interval in milliseconds; 0 means none.
*/
goog.testing.net.XhrIo.prototype.setTimeoutInterval = function(ms) {
this.timeoutInterval_ = Math.max(0, ms);
};
/**
* Causes timeout events to be fired.
*/
goog.testing.net.XhrIo.prototype.simulateTimeout = function() {
this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;
this.dispatchEvent(goog.net.EventType.TIMEOUT);
this.abort(goog.net.ErrorCode.TIMEOUT);
};
/**
* Abort the current XMLHttpRequest
* @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
* defaults to ABORT.
*/
goog.testing.net.XhrIo.prototype.abort = function(opt_failureCode) {
if (this.active_) {
this.active_ = false;
this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
this.dispatchEvent(goog.net.EventType.COMPLETE);
this.dispatchEvent(goog.net.EventType.ABORT);
}
};
/**
* Simulates the XhrIo send.
* @param {string} url Uri to make request too.
* @param {string=} opt_method Send method, default: GET.
* @param {string=} opt_content Post data.
* @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
* request.
*/
goog.testing.net.XhrIo.prototype.send = function(url, opt_method, opt_content,
opt_headers) {
if (this.active_) {
throw Error('[goog.net.XhrIo] Object is active with another request');
}
this.lastUri_ = url;
if (this.testQueue_) {
this.testQueue_.enqueue(['s', url, opt_method, opt_content, opt_headers]);
}
this.readyState_ = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.LOADING);
this.active_ = true;
};
/**
* Creates a new XHR object.
* @return {XMLHttpRequest|GearsHttpRequest} The newly created XHR object.
* @protected
*/
goog.testing.net.XhrIo.prototype.createXhr = function() {
return new goog.net.XmlHttp();
};
/**
* Simulates changing to the new ready state.
* @param {number} readyState Ready state to change to.
*/
goog.testing.net.XhrIo.prototype.simulateReadyStateChange =
function(readyState) {
if (readyState < this.readyState_) {
throw Error('Readystate cannot go backwards');
}
while (this.readyState_ < readyState) {
this.readyState_++;
this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);
if (this.readyState_ == goog.net.XmlHttp.ReadyState.COMPLETE) {
this.active_ = false;
this.dispatchEvent(goog.net.EventType.COMPLETE);
}
}
};
/**
* Simulates receiving a response.
* @param {number} statusCode Simulated status code.
* @param {string|Document} response Simulated response.
* @param {Object=} opt_headers Simulated response headers.
*/
goog.testing.net.XhrIo.prototype.simulateResponse = function(statusCode,
response, opt_headers) {
this.statusCode_ = statusCode;
this.response_ = response;
this.responseHeaders_ = opt_headers || {};
this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.COMPLETE);
if (this.isSuccess()) {
this.dispatchEvent(goog.net.EventType.SUCCESS);
} else {
this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;
this.lastError_ = this.getStatusText() + ' [' + this.getStatus() + ']';
this.dispatchEvent(goog.net.EventType.ERROR);
}
};
/**
* Simulates the Xhr is ready for the next request.
*/
goog.testing.net.XhrIo.prototype.simulateReady = function() {
this.dispatchEvent(goog.net.EventType.READY);
};
/**
* @return {boolean} Whether there is an active request.
*/
goog.testing.net.XhrIo.prototype.isActive = function() {
return this.active_;
};
/**
* Has the request completed.
* @return {boolean} Whether the request has completed.
*/
goog.testing.net.XhrIo.prototype.isComplete = function() {
return this.readyState_ == goog.net.XmlHttp.ReadyState.COMPLETE;
};
/**
* Has the request compeleted with a success.
* @return {boolean} Whether the request compeleted successfully.
*/
goog.testing.net.XhrIo.prototype.isSuccess = function() {
switch (this.statusCode_) {
case 0: // Used for local XHR requests
case 200: // HTTP Success
case 204: // HTTP Success - no content
case 304: // HTTP Cache
return true;
default:
return false;
}
};
/**
* Returns the readystate.
* @return {number} goog.net.XmlHttp.ReadyState.*.
*/
goog.testing.net.XhrIo.prototype.getReadyState = function() {
return this.readyState_;
};
/**
* Get the status from the Xhr object. Will only return correct result when
* called from the context of a callback.
* @return {number} Http status.
*/
goog.testing.net.XhrIo.prototype.getStatus = function() {
return this.statusCode_;
};
/**
* Get the status text from the Xhr object. Will only return correct result
* when called from the context of a callback.
* @return {string} Status text.
*/
goog.testing.net.XhrIo.prototype.getStatusText = function() {
return '';
};
/**
* Gets the last error message.
* @return {goog.net.ErrorCode} Last error code.
*/
goog.testing.net.XhrIo.prototype.getLastErrorCode = function() {
return this.lastErrorCode_;
};
/**
* Gets the last error message.
* @return {string} Last error message.
*/
goog.testing.net.XhrIo.prototype.getLastError = function() {
return this.lastError_;
};
/**
* Gets the last URI that was requested.
* @return {string} Last URI.
*/
goog.testing.net.XhrIo.prototype.getLastUri = function() {
return this.lastUri_;
};
/**
* Gets the response text from the Xhr object. Will only return correct result
* when called from the context of a callback.
* @return {string} Result from the server.
*/
goog.testing.net.XhrIo.prototype.getResponseText = function() {
return goog.isString(this.response_) ? this.response_ :
goog.dom.xml.serialize(this.response_);
};
/**
* Gets the response and evaluates it as JSON from the Xhr object. Will only
* return correct result when called from the context of a callback.
* @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for
* stripping of the response before parsing. This needs to be set only if
* your backend server prepends the same prefix string to the JSON response.
* @return {Object} JavaScript object.
*/
goog.testing.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {
var responseText = this.getResponseText();
if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {
responseText = responseText.substring(opt_xssiPrefix.length);
}
return goog.json.parse(responseText);
};
/**
* Gets the response XML from the Xhr object. Will only return correct result
* when called from the context of a callback.
* @return {Document} Result from the server if it was XML.
*/
goog.testing.net.XhrIo.prototype.getResponseXml = function() {
// NOTE(user): I haven't found out how to check in Internet Explorer
// whether the response is XML document, so I do it the other way around.
return goog.isString(this.response_) ? null : this.response_;
};
/**
* Get the value of the response-header with the given name from the Xhr object
* Will only return correct result when called from the context of a callback
* and the request has completed
* @param {string} key The name of the response-header to retrieve.
* @return {string|undefined} The value of the response-header named key.
*/
goog.testing.net.XhrIo.prototype.getResponseHeader = function(key) {
return this.isComplete() ? this.responseHeaders_[key] : undefined;
};