From a887bc4af94d3e0513afaab2c4f2dcc6607850e9 Mon Sep 17 00:00:00 2001 From: Izel Nakri Date: Sun, 29 Oct 2017 01:39:07 +0200 Subject: [PATCH] first pretender-hacks added --- index.js | 1 + lib/mem-server/pretender-hacks.js | 119 ++++++++++++++++++++++++++++++ lib/mem-server/server.js | 37 +++------- test/mem-server.response.js | 2 +- 4 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 lib/mem-server/pretender-hacks.js diff --git a/index.js b/index.js index 5a1f7aa..67b4412 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,7 @@ window.$ = require('jquery'); global.self = window.self; require('pretender'); +require('./lib/mem-server/pretender-hacks.js'); const MemServer = require('./lib/mem-server.js').default; diff --git a/lib/mem-server/pretender-hacks.js b/lib/mem-server/pretender-hacks.js new file mode 100644 index 0000000..2f05f31 --- /dev/null +++ b/lib/mem-server/pretender-hacks.js @@ -0,0 +1,119 @@ +// HACK START: Pretender Request Parameter Type Casting Hack: Because types are important. +window.Pretender.prototype._handlerFor = function(verb, url, request) { + var registry = this.hosts.forURL(url)[verb]; + var matches = registry.recognize(window.Pretender.parseURL(url).fullpath); + var match = matches ? matches[0] : null; + + if (match) { + request.params = Object.keys(match.params).reduce((result, key) => { + var value = match.params[key]; + + return Object.assign(result, { [key]: parseInt(value, 10) || value }); + }, {}); + request.queryParams = Object.keys(matches.queryParams).reduce((result, key) => { + var value = matches.queryParams[key]; + + return Object.assign(result, { [key]: parseInt(value, 10) || value }); + }, {}); + } + + return match; +}; +// END: Pretender Request Parameter Type Casting Hack + +// HACK START: Pretender Response Defaults Hack: Because Pretender Response types suck UX-wise. +window.Pretender.prototype.handleRequest = function(request) { + var pretender = this; + var verb = request.method.toUpperCase(); + var path = request.url; + var handler = this._handlerFor(verb, path, request); + + var _handleRequest = function(result) { + var statusCode, headers, body; + + if (Array.isArray(result) && result.length === 3) { + statusCode = result[0], + headers = pretender.prepareHeaders(result[1]), + body = pretender.prepareBody(result[2], headers); + + return pretender.handleResponse(request, async, function() { + request.respond(statusCode, headers, body); + pretender.handledRequest(verb, path, request); + }) + } else if (!result) { + if (verb === 'DELETE') { + headers = pretender.prepareHeaders({ 'Content-Type': 'application/json' }); + + return pretender.handleResponse(request, async, function() { + request.respond(204, headers, pretender.prepareBody({}, headers)); + pretender.handledRequest(verb, path, request); + }) + } + + throw new Error('Nothing returned by handler for ' + path + + '. Remember to return something in your route handler.'); + } + + var targetResult = typeof result === 'string' ? result : JSON.stringify(result); + + statusCode = getDefaultStatusCode(verb); + headers = pretender.prepareHeaders({ 'Content-Type': 'application/json' }); + body = pretender.prepareBody(targetResult, headers); + + pretender.handleResponse(request, async, function() { + request.respond(statusCode, headers, body); + pretender.handledRequest(verb, path, request); + }) + } + + if (handler) { + handler.handler.numberOfCalls++; + var async = handler.handler.async; + this.handledRequests.push(request); + + try { + var result = handler.handler(request); + + if (result && typeof result.then === 'function') { // `result` is a promise, resolve it + result.then(function(resolvedResult) { _handleRequest(resolvedResult); }); + } else { + _handleRequest(result); + } + } catch (error) { + this.erroredRequest(verb, path, request, error); + this.resolve(request); + } + } else { + if (!this.disableUnhandled) { + this.unhandledRequests.push(request); + this.unhandledRequest(verb, path, request); + } + } + + function getDefaultStatusCode(verb) { + if (['GET', 'PUT', 'PATCH'].includes(verb)) { + return 200; + } else if (verb === 'POST') { + return 201; + } else if (verb === 'DELETE') { + return 204; + } + + return 500; + } +} +// END: Pretender Response Defaults Hack + +// TODO: add shortcuts + timing + + + +// ['get', 'put', 'patch', 'post', 'delete'].forEach((verb) => { +// window.Pretender.prototype[verb] = function (path, handler, async) { +// // TODO: juggle with the handler? +// return this.register(verb, path, handler, async); +// } +// }) + +// also add timing here +// END: Pretender Response Defaults Hack diff --git a/lib/mem-server/server.js b/lib/mem-server/server.js index ede5629..8640bf8 100644 --- a/lib/mem-server/server.js +++ b/lib/mem-server/server.js @@ -2,29 +2,6 @@ import chalk from 'chalk'; const Server = require(`${process.cwd()}/memserver/server`).default; // NOTE: make this ES6 import -// START: Pretender Hack: Because types are important. -window.Pretender.prototype._handlerFor = function(verb, url, request) { - var registry = this.hosts.forURL(url)[verb]; - var matches = registry.recognize(window.Pretender.parseURL(url).fullpath); - var match = matches ? matches[0] : null; - - if (match) { - request.params = Object.keys(match.params).reduce((result, key) => { - var value = match.params[key]; - - return Object.assign(result, { [key]: parseInt(value, 10) || value }); - }, {}); - request.queryParams = Object.keys(matches.queryParams).reduce((result, key) => { - var value = matches.queryParams[key]; - - return Object.assign(result, { [key]: parseInt(value, 10) || value }); - }, {}); - } - - return match; -}; -// END: Pretender Hack: Because types are important. - export default function(options) { let pretender = new window.Pretender(function() { const MemServer = chalk.cyan('[MemServer]'); @@ -44,10 +21,20 @@ export default function(options) { console.log(chalk.red('UNHANDLED REQUEST WAS:\n'), request); console.log(request); } + + this.erroredRequest = function(verb, path, request, error) { + console.log('erroredRequest'); + console.log('verb', verb); + console.log('path', path); + console.log('request', request); + console.log('error', error); + // console.warn("There was an error", error); + } }); Server.apply(pretender, [global.MemServer.Models]) - + // eval(pry.it); + // TODO: intercept Server.get, post, put, delete. put default responses return pretender; } @@ -81,7 +68,7 @@ function colorStatusCode(statusCode) { // status code defaults: // GET is 200 -// PUT/PATCH is 204 +// PUT/PATCH is 200 // POST is 201 // DEL is 204 diff --git a/test/mem-server.response.js b/test/mem-server.response.js index 04ee466..318e04c 100644 --- a/test/mem-server.response.js +++ b/test/mem-server.response.js @@ -18,7 +18,7 @@ describe('MemServer.Response Interface', function() { this.get('/photos', () => { const photos = Photo.findAll(); - return [200, {'Content-Type': 'application/json'}, JSON.stringify({ photos: Photo.serializer(photos) })] + return { photos: Photo.serializer(photos) }; }); }`); fs.mkdirSync(`./memserver/fixtures`);