xhr-mock
Version:
Utility for mocking XMLHttpRequest.
683 lines (682 loc) • 33.7 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var MockURL_1 = require("./MockURL");
var MockRequest_1 = require("./MockRequest");
var MockResponse_1 = require("./MockResponse");
var MockEvent_1 = require("./MockEvent");
var MockProgressEvent_1 = require("./MockProgressEvent");
var MockXMLHttpRequestUpload_1 = require("./MockXMLHttpRequestUpload");
var MockXMLHttpRequestEventTarget_1 = require("./MockXMLHttpRequestEventTarget");
var handle_1 = require("./handle");
var formatError_1 = require("./formatError");
var MockError_1 = require("./MockError");
var notImplementedError = new MockError_1.MockError("This feature hasn't been implmented yet. Please submit an Issue or Pull Request on Github.");
// implemented according to https://xhr.spec.whatwg.org/
var FORBIDDEN_METHODS = ['CONNECT', 'TRACE', 'TRACK'];
var ReadyState;
(function (ReadyState) {
ReadyState[ReadyState["UNSENT"] = 0] = "UNSENT";
ReadyState[ReadyState["OPENED"] = 1] = "OPENED";
ReadyState[ReadyState["HEADERS_RECEIVED"] = 2] = "HEADERS_RECEIVED";
ReadyState[ReadyState["LOADING"] = 3] = "LOADING";
ReadyState[ReadyState["DONE"] = 4] = "DONE";
})(ReadyState = exports.ReadyState || (exports.ReadyState = {}));
function calculateProgress(req) {
var header = req.header('content-length');
var body = req.body();
var lengthComputable = false;
var total = 0;
if (header) {
var contentLength = parseInt(header, 10);
if (contentLength !== NaN) {
lengthComputable = true;
total = contentLength;
}
}
return {
lengthComputable: lengthComputable,
loaded: (body && body.length) || 0,
total: total
};
}
// @ts-ignore: https://github.com/jameslnewell/xhr-mock/issues/45
var MockXMLHttpRequest = /** @class */ (function (_super) {
__extends(MockXMLHttpRequest, _super);
function MockXMLHttpRequest() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.UNSENT = ReadyState.UNSENT;
_this.OPENED = ReadyState.OPENED;
_this.HEADERS_RECEIVED = ReadyState.HEADERS_RECEIVED;
_this.LOADING = ReadyState.LOADING;
_this.DONE = ReadyState.DONE;
//some libraries (like Mixpanel) use the presence of this field to check if XHR is properly supported
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
_this.withCredentials = false;
_this.req = new MockRequest_1.default();
_this.res = new MockResponse_1.default();
_this.responseType = '';
_this.responseURL = '';
_this._timeout = 0;
// @ts-ignore: https://github.com/jameslnewell/xhr-mock/issues/45
_this.upload = new MockXMLHttpRequestUpload_1.default();
_this.readyState = MockXMLHttpRequest.UNSENT;
// flags
_this.isSynchronous = false;
_this.isSending = false;
_this.isUploadComplete = false;
_this.isAborted = false;
_this.isTimedOut = false;
return _this;
}
/**
* Add a mock handler
*/
MockXMLHttpRequest.addHandler = function (fn) {
this.handlers.push(fn);
};
/**
* Remove a mock handler
*/
MockXMLHttpRequest.removeHandler = function (fn) {
throw notImplementedError;
};
/**
* Remove all request handlers
*/
MockXMLHttpRequest.removeAllHandlers = function () {
this.handlers = [];
};
Object.defineProperty(MockXMLHttpRequest.prototype, "timeout", {
get: function () {
return this._timeout;
},
set: function (timeout) {
if (timeout !== 0 && this.isSynchronous) {
throw new MockError_1.MockError('Timeouts cannot be set for synchronous requests made from a document.');
}
this._timeout = timeout;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MockXMLHttpRequest.prototype, "response", {
// https://xhr.spec.whatwg.org/#the-response-attribute
get: function () {
if (this.responseType === '' || this.responseType === 'text') {
if (this.readyState !== this.LOADING && this.readyState !== this.DONE) {
return '';
}
return this.responseText;
}
if (this.readyState !== this.DONE) {
return null;
}
var body = this.res.body();
if (!body) {
return null;
}
if (this.responseType === 'json' && typeof body === 'string') {
try {
return JSON.parse(this.responseText);
}
catch (error) {
return null;
}
}
if (this.responseType === 'blob' && typeof body === 'string') {
try {
throw notImplementedError;
}
catch (error) {
return null;
}
}
if (this.responseType === 'arraybuffer' && typeof body === 'string') {
try {
throw notImplementedError;
}
catch (error) {
return null;
}
}
if (this.responseType === 'document' && typeof body === 'string') {
try {
throw notImplementedError;
}
catch (error) {
return null;
}
}
// rely on the mock to do the right thing with an arraybuffer, blob or document
return body;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MockXMLHttpRequest.prototype, "responseText", {
get: function () {
return this.res.body() || '';
},
enumerable: true,
configurable: true
});
Object.defineProperty(MockXMLHttpRequest.prototype, "responseXML", {
get: function () {
throw notImplementedError;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MockXMLHttpRequest.prototype, "status", {
get: function () {
return this.res.status();
},
enumerable: true,
configurable: true
});
Object.defineProperty(MockXMLHttpRequest.prototype, "statusText", {
get: function () {
return this.res.reason();
},
enumerable: true,
configurable: true
});
MockXMLHttpRequest.prototype.getAllResponseHeaders = function () {
// I'm pretty sure this fn can return null, but TS types say no
// if (this.readyState < MockXMLHttpRequest.HEADERS_RECEIVED) {
// return null;
// }
var headers = this.res.headers();
var result = Object.keys(headers)
.map(function (name) { return name + ": " + headers[name] + "\r\n"; })
.join('');
return result;
};
MockXMLHttpRequest.prototype.getResponseHeader = function (name) {
if (this.readyState < MockXMLHttpRequest.HEADERS_RECEIVED) {
return null;
}
return this.res.header(name);
};
MockXMLHttpRequest.prototype.setRequestHeader = function (name, value) {
if (this.readyState < MockXMLHttpRequest.OPENED) {
throw new MockError_1.MockError('xhr must be OPENED.');
}
this.req.header(name, value);
};
MockXMLHttpRequest.prototype.overrideMimeType = function (mime) {
throw notImplementedError;
};
MockXMLHttpRequest.prototype.open = function (method, url, async, username, password) {
if (async === void 0) { async = true; }
if (username === void 0) { username = null; }
if (password === void 0) { password = null; }
// if method is not a method, then throw a "SyntaxError" DOMException
// if method is a forbidden method, then throw a "SecurityError" DOMException
if (FORBIDDEN_METHODS.indexOf(method) !== -1) {
throw new MockError_1.MockError("Method " + method + " is forbidden.");
}
// normalize method
method = method.toUpperCase();
// let parsedURL be the result of parsing url with settingsObject’s API base URL and settingsObject’s API URL character encoding
// if parsedURL is failure, then throw a "SyntaxError" DOMException
var fullURL = MockURL_1.parseURL(url);
// if the async argument is omitted, set async to true, and set username and password to null.
// if parsedURL’s host is non-null, run these substeps:
// if the username argument is not null, set the username given parsedURL and username
// if the password argument is not null, set the password given parsedURL and password
fullURL.username = username || '';
fullURL.password = (username && password) || '';
// if async is false, current global object is a Window object, and the timeout attribute value
// is not zero or the responseType attribute value is not the empty string, then throw an "InvalidAccessError" DOMException.
if (!async && (this._timeout !== 0 || this.responseType !== '')) {
throw new MockError_1.MockError('InvalidAccessError');
}
// terminate the ongoing fetch operated by the XMLHttpRequest object
if (this.isSending) {
throw new MockError_1.MockError('Unable to terminate the previous request');
}
// set variables associated with the object as follows:
// - unset the send() flag and upload listener flag
// - set the synchronous flag, if async is false, and unset the synchronous flag otherwise
// - set request method to method
// - set request URL to parsedURL
// - empty author request headers
this.isSending = false;
this.isSynchronous = !async;
this.req
.method(method)
.headers({})
.url(MockURL_1.formatURL(fullURL));
this.applyNetworkError();
// if the state is not opened, run these substeps:
if (this.readyState !== this.OPENED) {
// set state to opened
this.readyState = MockXMLHttpRequest.OPENED;
// fire an event named readystatechange
this.dispatchEvent(new MockEvent_1.default('readystatechange'));
}
};
MockXMLHttpRequest.prototype.sendSync = function () {
// let response be the result of fetching req
var res;
try {
res = handle_1.sync(MockXMLHttpRequest.handlers, this.req, this.res);
// if the timeout attribute value is not zero, then set the timed out flag and terminate fetching if it has not returned within the amount of milliseconds from the timeout.
// TODO: check if timeout was elapsed
//if response’s body is null, then run handle response end-of-body and return
// let reader be the result of getting a reader from response’s body’s stream
// let promise be the result of reading all bytes from response’s body’s stream with reader
// wait for promise to be fulfilled or rejected
// if promise is fulfilled with bytes, then append bytes to received bytes
// run handle response end-of-body for response
this.handleResponseBody(res);
}
catch (error) {
MockXMLHttpRequest.errorCallback({ req: this.req, err: error });
this.handleError(error);
}
};
MockXMLHttpRequest.prototype.sendAsync = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var req, progress, progress_1, res, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
req = this.req;
progress = calculateProgress(this.res);
this.dispatchEvent(new MockProgressEvent_1.default('loadstart', __assign({}, progress, { loaded: 0 })));
// if the upload complete flag is unset and upload listener flag is set, then fire a progress
// event named loadstart on the XMLHttpRequestUpload object with 0 and req’s body’s total bytes.
if (!this.isUploadComplete) {
progress_1 = calculateProgress(this.req);
this.upload.dispatchEvent(new MockProgressEvent_1.default('loadstart', __assign({}, progress_1, { loaded: 0 })));
}
// if state is not opened or the send() flag is unset, then return.
if (this.readyState !== this.OPENED || !this.isSending) {
return [2 /*return*/];
}
// fetch req. Handle the tasks queued on the networking task source per below
// run these subsubsteps in parallel:
// wait until either req’s done flag is set or
// the timeout attribute value number of milliseconds has passed since these subsubsteps started
// while timeout attribute value is not zero
// if req’s done flag is unset, then set the timed out flag and terminate fetching
if (this._timeout !== 0) {
// @ts-ignore: wants a NodeJS.Timer because of @types/node
this._timeoutTimer = setTimeout(function () {
_this.isTimedOut = true;
_this.handleError();
}, this._timeout);
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, handle_1.async(MockXMLHttpRequest.handlers, this.req, this.res)];
case 2:
res = _a.sent();
//we've received a response before the timeout so we don't want to timeout
clearTimeout(this._timeoutTimer);
if (this.isAborted || this.isTimedOut) {
return [2 /*return*/]; // these cases will already have been handled
}
this.sendRequest(req);
this.receiveResponse(res);
return [3 /*break*/, 4];
case 3:
error_1 = _a.sent();
//we've received an error before the timeout so we don't want to timeout
clearTimeout(this._timeoutTimer);
if (this.isAborted || this.isTimedOut) {
return [2 /*return*/]; // these cases will already have been handled
}
MockXMLHttpRequest.errorCallback({ req: this.req, err: error_1 });
this.handleError(error_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
};
MockXMLHttpRequest.prototype.applyNetworkError = function () {
// a network error is a response whose status is always 0, status message is always the
// empty byte sequence, header list is always empty, body is always null, and
// trailer is always empty
this.res
.status(0)
.reason('')
.headers({})
.body(null);
};
// @see https://xhr.spec.whatwg.org/#request-error-steps
MockXMLHttpRequest.prototype.reportError = function (event) {
// set state to done
this.readyState = this.DONE;
// unset the send() flag
this.isSending = false;
// set response to network error
this.applyNetworkError();
// if the synchronous flag is set, throw an exception exception
if (this.isSynchronous) {
throw new MockError_1.MockError('An error occurred whilst sending a synchronous request.');
}
// fire an event named readystatechange
this.dispatchEvent(new MockEvent_1.default('readystatechange'));
// if the upload complete flag is unset, follow these substeps:
if (!this.isUploadComplete) {
// set the upload complete flag
this.isUploadComplete = true;
// if upload listener flag is unset, then terminate these substeps
// NOTE: not sure why this is necessary - if there's no listeners listening, then the
// following events have no impact
var uploadProgress = calculateProgress(this.req);
// fire a progress event named event on the XMLHttpRequestUpload object with 0 and 0
this.upload.dispatchEvent(new MockProgressEvent_1.default(event, uploadProgress));
// fire a progress event named loadend on the XMLHttpRequestUpload object with 0 and 0
this.upload.dispatchEvent(new MockProgressEvent_1.default('loadend', uploadProgress));
}
var downloadProgress = calculateProgress(this.res);
// fire a progress event named event with 0 and 0
this.dispatchEvent(new MockProgressEvent_1.default(event, downloadProgress));
// fire a progress event named loadend with 0 and 0
this.dispatchEvent(new MockProgressEvent_1.default('loadend', downloadProgress));
};
MockXMLHttpRequest.prototype.sendRequest = function (req) {
if (this.isUploadComplete) {
return;
}
// if not roughly 50ms have passed since these subsubsteps were last invoked, terminate these subsubsteps
// TODO:
// If upload listener flag is set, then fire a progress event named progress on the
// XMLHttpRequestUpload object with request’s body’s transmitted bytes and request’s body’s
// total bytes
// const progress = getProgress(this.req);
// this.upload.dispatchEvent(new MockProgressEvent('progress', {
// ...progress,
// loaded: %
// }))
// TODO: repeat this in a timeout to simulate progress events
// TODO: dispatch total, length and lengthComputable values
// set the upload complete flag
this.isUploadComplete = true;
// if upload listener flag is unset, then terminate these subsubsteps.
// NOTE: it doesn't really matter if we emit these events and noone is listening
// let transmitted be request’s body’s transmitted bytes
// let length be request’s body’s total bytes
var progress = calculateProgress(this.req);
// fire a progress event named progress on the XMLHttpRequestUpload object with transmitted and length
this.upload.dispatchEvent(new MockProgressEvent_1.default('progress', progress));
// fire a progress event named load on the XMLHttpRequestUpload object with transmitted and length
this.upload.dispatchEvent(new MockProgressEvent_1.default('load', progress));
// fire a progress event named loadend on the XMLHttpRequestUpload object with transmitted and length
this.upload.dispatchEvent(new MockProgressEvent_1.default('loadend', progress));
};
MockXMLHttpRequest.prototype.receiveResponse = function (res) {
// set state to headers received
this.readyState = this.HEADERS_RECEIVED;
// fire an event named readystatechange
this.dispatchEvent(new MockEvent_1.default('readystatechange'));
// if state is not headers received, then return
// NOTE: is that really necessary, we've just change the state a second ago
// if response’s body is null, then run handle response end-of-body and return
if (res.body() === null) {
this.handleResponseBody(res);
return;
}
// let reader be the result of getting a reader from response’s body’s stream
// let read be the result of reading a chunk from response’s body’s stream with reader
// When read is fulfilled with an object whose done property is false and whose value property
// is a Uint8Array object, run these subsubsubsteps and then run the above subsubstep again:
// TODO:
// append the value property to received bytes
// if not roughly 50ms have passed since these subsubsubsteps were last invoked, then terminate
// these subsubsubsteps
// TODO:
// if state is headers received, then set state to loading
// NOTE: why wouldn't it be headers received?
this.readyState = this.LOADING;
// fire an event named readystatechange
this.dispatchEvent(new MockEvent_1.default('readystatechange'));
// fire a progress event named progress with response’s body’s transmitted bytes and response’s
// body’s total bytes
// TODO: repeat to simulate progress
// const progress = calculateProgress(res);
// this.dispatchEvent(new MockProgressEvent('progress', {
// ...progress,
// loaded: %
// }));
// when read is fulfilled with an object whose done property is true, run handle response
// end-of-body for response
// when read is rejected with an exception, run handle errors for response
// NOTE: we don't handle this error case
this.handleResponseBody(res);
};
// @see https://xhr.spec.whatwg.org/#handle-errors
MockXMLHttpRequest.prototype.handleError = function (error) {
// if the send() flag is unset, return
if (!this.isSending) {
return;
}
// if the timed out flag is set, then run the request error steps for event timeout and exception TimeoutError
if (this.isTimedOut) {
this.reportError('timeout');
return;
}
// otherwise, if response’s body’s stream is errored, then:
// NOTE: we're not handling this event
// if () {
// // set state to done
// this.readyState = this.DONE;
// // unset the send() flag
// this.isSending = false;
// // set response to a network error
// this.applyNetworkError();
// return;
// }
// otherwise, if response’s aborted flag is set, then run the request error steps for event abort and exception AbortError
if (this.isAborted) {
this.reportError('abort');
return;
}
// if response is a network error, run the request error steps for event error and exception NetworkError
// NOTE: we assume all other calls are network errors
this.reportError('error');
};
// @see https://xhr.spec.whatwg.org/#handle-response-end-of-body
MockXMLHttpRequest.prototype.handleResponseBody = function (res) {
this.res = res;
// let transmitted be response’s body’s transmitted bytes
// let length be response’s body’s total bytes.
var progress = calculateProgress(res);
// if the synchronous flag is unset, update response’s body using response
if (!this.isSynchronous) {
// fire a progress event named progress with transmitted and length
this.dispatchEvent(new MockProgressEvent_1.default('progress', progress));
}
// set state to done
this.readyState = this.DONE;
// unset the send() flag
this.isSending = false;
// fire an event named readystatechange
this.dispatchEvent(new MockEvent_1.default('readystatechange'));
// fire a progress event named load with transmitted and length
this.dispatchEvent(new MockProgressEvent_1.default('load', progress));
// fire a progress event named loadend with transmitted and length
this.dispatchEvent(new MockProgressEvent_1.default('loadend', progress));
};
MockXMLHttpRequest.prototype.send = function (body) {
// if state is not opened, throw an InvalidStateError exception
if (this.readyState !== MockXMLHttpRequest.OPENED) {
throw new MockError_1.MockError('Please call MockXMLHttpRequest.open() before MockXMLHttpRequest.send().');
}
// if the send() flag is set, throw an InvalidStateError exception
if (this.isSending) {
throw new MockError_1.MockError('MockXMLHttpRequest.send() has already been called.');
}
// if the request method is GET or HEAD, set body to null
if (this.req.method() === 'GET' || this.req.method() === 'HEAD') {
body = null;
}
// if body is null, go to the next step otherwise, let encoding and mimeType be null, and then follow these rules, switching on body
var encoding;
var mimeType;
if (body !== null && body !== undefined) {
if (typeof Document !== 'undefined' &&
typeof XMLDocument !== 'undefined' &&
body instanceof Document) {
// Set encoding to `UTF-8`.
// Set mimeType to `text/html` if body is an HTML document, and to `application/xml` otherwise. Then append `;charset=UTF-8` to mimeType.
// Set request body to body, serialized, converted to Unicode, and utf-8 encoded.
encoding = 'UTF-8';
mimeType =
body instanceof XMLDocument ? 'application/xml' : 'text/html';
}
else {
// If body is a string, set encoding to `UTF-8`.
// Set request body and mimeType to the result of extracting body.
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
if (typeof Blob !== 'undefined' && body instanceof Blob) {
mimeType = body.type;
}
else if (typeof FormData !== 'undefined' &&
body instanceof FormData) {
mimeType = 'multipart/form-data; boundary=----XHRMockFormBoundary';
}
else if (typeof URLSearchParams !== 'undefined' &&
body instanceof URLSearchParams) {
encoding = 'UTF-8';
mimeType = 'application/x-www-form-urlencoded';
}
else if (typeof body === 'string') {
encoding = 'UTF-8';
mimeType = 'text/plain';
}
else {
throw notImplementedError;
}
}
// if mimeType is non-null and author request headers does not contain `Content-Type`, then append `Content-Type`/mimeType to author request headers.
// otherwise, if the header whose name is a byte-case-insensitive match for `Content-Type` in author request headers has a value that is a valid MIME type,
// which has a `charset` parameter whose value is not a byte-case-insensitive match for encoding, and encoding is not null, then set all the `charset` parameters
// whose value is not a byte-case-insensitive match for encoding of that header’s value to encoding.
// chrome seems to forget the second case ^^^
var contentType = this.req.header('content-type');
if (!contentType) {
this.req.header('content-type', encoding ? mimeType + "; charset=" + encoding : mimeType);
}
this.req.body(body);
}
// if one or more event listeners are registered on the associated XMLHttpRequestUpload object, then set upload listener flag
// Note: not really necessary since dispatching an event to no listeners doesn't hurt anybody
//TODO: check CORs
// unset the upload complete flag
this.isUploadComplete = false;
// unset the timed out flag
this.isTimedOut = false;
// if req’s body is null, set the upload complete flag
if (body === null || body === undefined) {
this.isUploadComplete = true;
}
// set the send() flag
this.isSending = true;
if (this.isSynchronous) {
this.sendSync();
}
else {
this.sendAsync();
}
};
MockXMLHttpRequest.prototype.abort = function () {
//we've cancelling the response before the timeout period so we don't want to timeout
clearTimeout(this._timeoutTimer);
// terminate the ongoing fetch with the aborted flag set
this.isAborted = true;
// if state is either opened with the send() flag set, headers received, or loading,
// run the request error steps for event
if (this.readyState === this.OPENED ||
this.readyState === this.HEADERS_RECEIVED ||
this.readyState === this.LOADING) {
this.reportError('abort');
}
// if state is done, then set state to unsent and response to a network error
if (this.readyState === this.DONE) {
this.readyState = this.UNSENT;
this.applyNetworkError();
return;
}
};
MockXMLHttpRequest.prototype.msCachingEnabled = function () {
return false;
};
MockXMLHttpRequest.UNSENT = ReadyState.UNSENT;
MockXMLHttpRequest.OPENED = ReadyState.OPENED;
MockXMLHttpRequest.HEADERS_RECEIVED = ReadyState.HEADERS_RECEIVED;
MockXMLHttpRequest.LOADING = ReadyState.LOADING;
MockXMLHttpRequest.DONE = ReadyState.DONE;
MockXMLHttpRequest.handlers = [];
MockXMLHttpRequest.errorCallback = function (_a) {
var req = _a.req, err = _a.err;
if (err instanceof MockError_1.MockError) {
console.error(formatError_1.formatError(err.message, req));
}
else {
console.error(formatError_1.formatError('A handler returned an error for the request.', req, err));
}
};
return MockXMLHttpRequest;
}(MockXMLHttpRequestEventTarget_1.default));
exports.default = MockXMLHttpRequest;