UNPKG

slush-gladius

Version:

Slush generator for bleeding edge weapo... ehr, applications!

143 lines (122 loc) 4.24 kB
var RouteRecognizer = require('./route-recognizer.js')['default']; var FakeXMLHttpRequest = require('./fakexmlhttprequest.js'); function Pretender(maps){ maps = maps || function(){}; // Herein we keep track of RouteRecognizer instances // keyed by HTTP method. Feel free to add more as needed. this.registry = { GET: new RouteRecognizer(), PUT: new RouteRecognizer(), POST: new RouteRecognizer(), DELETE: new RouteRecognizer(), PATCH: new RouteRecognizer(), HEAD: new RouteRecognizer() }; this.handlers = []; this.handledRequests = []; this.unhandledRequests = []; // reference the native XMLHttpRequest object so // it can be restored later this._nativeXMLHttpRequest = window.XMLHttpRequest; // capture xhr requests, channeling them into // the route map. window.XMLHttpRequest = this.__fakeXMLHttpRequest = interceptor(this); // trigger the route map DSL. maps.call(this); } function interceptor(pretender) { function FakeRequest(){ // super() FakeXMLHttpRequest.call(this); } // extend var proto = new FakeXMLHttpRequest(); proto.send = function send(){ setTimeout(function() { FakeXMLHttpRequest.prototype.send.apply(this, arguments); pretender.handleRequest(this); }.bind(this), 200); }; FakeRequest.prototype = proto; return FakeRequest; } function verbify(verb){ return function(path, handler){ this.register(verb, path, handler); }; } function throwIfURLDetected(url){ var HTTP_REGEXP = /^https?/; var message; if(HTTP_REGEXP.test(url)) { var parser = window.document.createElement('a'); parser.href = url; message = "Pretender will not respond to requests for URLs. It is not possible to accurately simluate the browser's CSP. "+ "Remove the " + parser.protocol +"//"+ parser.hostname +" from " + url + " and try again"; throw new Error(message) } } Pretender.prototype = { get: verbify('GET'), post: verbify('POST'), put: verbify('PUT'), 'delete': verbify('DELETE'), patch: verbify('PATCH'), head: verbify('HEAD'), register: function register(verb, path, handler){ handler.numberOfCalls = 0; this.handlers.push(handler); var registry = this.registry[verb]; registry.add([{path: path, handler: handler}]); }, handleRequest: function handleRequest(request){ var verb = request.method.toUpperCase(); var path = request.url; throwIfURLDetected(path); var handler = this._handlerFor(verb, path, request); if (handler) { handler.handler.numberOfCalls++; this.handledRequests.push(request); try { var statusHeadersAndBody = handler.handler(request), status = statusHeadersAndBody[0], headers = this.prepareHeaders(statusHeadersAndBody[1]), body = this.prepareBody(statusHeadersAndBody[2]); request.respond(status, headers, body); this.handledRequest(verb, path, request); } catch (error) { this.erroredRequest(verb, path, request, error); } } else { this.unhandledRequests.push(request); this.unhandledRequest(verb, path, request); } }, prepareBody: function(body) { return body; }, prepareHeaders: function(headers) { return headers; }, handledRequest: function(verb, path, request) { /* no-op */}, unhandledRequest: function(verb, path, request) { throw new Error("Pretender intercepted "+verb+" "+path+" but no handler was defined for this type of request"); }, erroredRequest: function(verb, path, request, error){ error.message = "Pretender intercepted "+verb+" "+path+" but encountered an error: " + error.message; throw error; }, _handlerFor: function(verb, path, request){ var registry = this.registry[verb]; var matches = registry.recognize(path); var match = matches ? matches[0] : null; if (match) { request.params = match.params; request.queryParams = matches.queryParams; } return match; }, shutdown: function shutdown(){ window.XMLHttpRequest = this._nativeXMLHttpRequest; }, restart: function restart() { window.XMLHttpRequest = this.__fakeXMLHttpRequest; } }; module.exports.Pretender = Pretender;