mocks/xmlhttprequest.js

Summary

Maintainability
A
3 hrs
Test Coverage
'use strict';


window.XMLHttpRequest = function XMLHttpRequestMock() {};

_.extendProto(window.XMLHttpRequest, {
    open: open,
    setRequestHeader: setRequestHeader,
    send: send,
});

_.extend(window.XMLHttpRequest, {
    setMockRoutes: setMockRoutes,
    setOptions: setOptions
});


var _mock_routes, _opts = {};

function setMockRoutes(routes) {
    _mock_routes = routes;
}

function setOptions(opts) {
    _opts = opts || {};
}


function open(method, url) {
    this.method = method;
    this.url = url;
    this.headers = {};
}


function setRequestHeader(header, content) {
    this.headers[header] = content;
}


function send(data) {
    var self = this;
    this.data = data;
    var url = this.url;
    var methodRoutes = _mock_routes && _mock_routes[this.method.toUpperCase()] || {};

    var handlerKey = _.find(Object.keys(methodRoutes), function(regex) {
        return url.match(new RegExp(regex));
    });

    var handler = methodRoutes[handlerKey];

    if (handler === undefined) {
        milo.util.logger.error('*unknown mock route', this.method, this.url);
        done({
            status: 404,
            body: 'unknown mock route: ' + this.method + ' ' + this.url
        });
    } else {
        if (typeof handler == 'function') {
            if (handler.length == 2) handler(data, done);
            else done(handler(data));
        } else
            done(handler);
    }

    function done(res) {
        var delay = _opts && _opts.delay;
        if (delay) _.delayMethod(self, _response_ready, delay, res);
        else _.deferMethod(self, _response_ready, res);
    }
}


function _response_ready(response) {
    var self = this;
    var handler, eventType;
    if (!setHandler('loadend'))
        if (!setHandler('readystatechange'))
            return milo.util.logger.warn('no request handler');

    this.readyState = 4;
    if (typeof response == 'object') {
        this.statusText = 'Error';
        this.status = response.status;
        this.responseText = response.body;
    } else {
        this.statusText = 'OK';
        this.status = 200;
        this.responseText = response;
    }
    handler({ type: eventType });

    function setHandler(et) {
        if (typeof self['on' + et] == 'function') {
            handler = self['on' + et];
            eventType = et;
            return true;
        }
    }
}