Skip to content

Instantly share code, notes, and snippets.

@feliperohdee
Created April 28, 2016 15:11
Show Gist options
  • Save feliperohdee/8dd85a4abe79b7412c755b31e51a7e86 to your computer and use it in GitHub Desktop.
Save feliperohdee/8dd85a4abe79b7412c755b31e51a7e86 to your computer and use it in GitHub Desktop.
import * as _ from 'lodash';
let root: any = window;
enum xhrStates {
UNSENT,
OPENED,
HEADERS_RECEIVED,
LOADING,
DONE
}
export class XMLHttpRequestMocks {
private static requests: Array<XMLHttpRequestMocks> = [];
private static recentRequest: XMLHttpRequestMocks;
public static XHR: XMLHttpRequest;
static beforeEach(): void {
XMLHttpRequestMocks.XHR = root.XMLHttpRequest;
root.XMLHttpRequest = XMLHttpRequestMocks;
}
static afterEach(): void {
XMLHttpRequestMocks.clearRequest();
root.XMLHttpRequest = XMLHttpRequestMocks.XHR;
}
static get mostRecent(): XMLHttpRequestMocks {
return XMLHttpRequestMocks.recentRequest;
}
static get allRequests(): Array<XMLHttpRequestMocks> {
return XMLHttpRequestMocks.requests;
}
static clearRequest(): void {
XMLHttpRequestMocks.requests.length = 0;
XMLHttpRequestMocks.recentRequest = null;
}
private previousRequest: XMLHttpRequestMocks;
private responseType: string = '';
private eventHandlers: Array<any> = [];
private readyState: number = 0;
private user: any;
private password: any;
private responseHeaders: any;
private status: any;
private responseText: string;
private response: any;
url: any;
method: any;
data: any;
requestHeaders: any = {};
constructor() {
this.previousRequest = XMLHttpRequestMocks.recentRequest;
XMLHttpRequestMocks.recentRequest = this;
XMLHttpRequestMocks.requests.push(this);
}
send(data: any): void {
this.data = data;
}
open(method: any, url: any, async: any, user: any, password: any): void {
this.method = method;
this.url = url;
this.user = user;
this.password = password;
this.readyState = xhrStates.OPENED;
this.triggerEvent('readyStateChange');
}
abort(): void {
if (this.readyState > xhrStates.UNSENT && this.readyState < xhrStates.DONE) {
this.readyState = xhrStates.UNSENT;
this.triggerEvent('abort');
}
}
setRequestHeader(key: any, value: any): void {
this.requestHeaders[key] = value;
}
addEventListener(name: string, handler: any): void {
this.eventHandlers.push({ name: name, handler: handler });
}
removeEventListener(name: string, handler: any): void {
_.each(this.eventHandlers, (ev, index) => {
if (ev.name === name && ev.handler === handler) {
this.eventHandlers.splice(index, 1);
}
});
}
throwError(err: any): void {
// TODO: something better with errors
this.triggerEvent('error');
}
respondWith(response: any): void {
this.readyState = xhrStates.DONE;
this.responseHeaders = {
'Content-Type': response.contentType || 'text/plain'
};
this.status = response.status || 200;
this.responseText = response.responseText;
if (!('response' in response)) {
switch (this.responseType) {
case 'json':
try {
this.response = JSON.parse(response.responseText);
} catch (err) {
throw new Error('unable to JSON.parse: \n' + response.responseText);
}
break;
case 'text':
this.response = response.responseText;
break;
default:
throw new Error('unhandled type "' + this.responseType + '"');
}
}
// TODO: pass better event to onload.
this.triggerEvent('load');
this.triggerEvent('readystatechange');
}
triggerEvent(name: any, eventObj?: any): void {
// TODO: create a better default event
const e: any = eventObj || {};
if (this['on' + name]) {
this['on' + name](e);
}
_.each(this.eventHandlers, function(eh) {
if (eh.name === name) {
eh.handler.call(this, e);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment