js-facade
Version:
Front end testing helpers!
1 lines • 8.34 kB
JavaScript
(function(){"use strict";function e(){Y=_.clone(Facade.resources,!0),I=_.clone(Facade.db,!0),U=_.clone(H,!0)}function r(e){n(e),t(e)}function n(e){_.each(l(),function(r){var n={resource:e,method:r.method};r.createWith(n),w(n)})}function t(e){var r=b(e);_.each(r,function(r){o(e,r)})}function o(e,r){_.each(f(),function(n){var t={resource:e,item:r,method:n.method};n.createWith(t),w(t)}),_.each(j,function(e){e.onItem&&(e.item=r,h(e),w(e))})}function i(e){Facade.backend.whenGET(e.resource.url+"/"+e.item.id).respond(function(r,n,t,o){var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){var r=R(e.resource,e.item.id);return[200,JSON.stringify(r),{},"OK"]});return a})}function a(e){Facade.backend.whenPUT(e.resource.url+"/"+e.item.id).respond(function(r,n,t,o){t=t||{};var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){var r=R(e.resource,e.item.id);return _.assign(r,JSON.parse(t)),[200,JSON.stringify(r),o,"OK"]});return a})}function u(e){Facade.backend.whenPATCH(e.resource.url+"/"+e.item.id).respond(function(r,n,t,o){t=t||{};var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){var r=R(e.resource,e.item.id);return _.assign(r,JSON.parse(t)),[200,JSON.stringify(r),o,"OK"]});return a})}function c(e){Facade.backend.whenDELETE(e.resource.url+"/"+e.item.id).respond(function(r,n,t,o){t=t||{};var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){var r=O(e.resource)["delete"](e.item.id);return[200,JSON.stringify(r),{},"OK"]});return a})}function s(e){Facade.backend.whenPOST(e.resource.url).respond(function(r,n,t,o){t=t||{},t=JSON.parse(t);var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){var r=_.isFunction(e.resource.createDefault)&&e.resource.createDefault(t);return r=r||t,e.resource.addItem(r),[200,JSON.stringify(r),{},"OK"]});return a})}function d(e){Facade.backend.whenGET(e.resource.url).respond(function(r,n,t,o){var i=Facade.findRoute(r,n),a=i.getSpecialResponseOr(function(){return[200,b(e.resource),{},"OK"]});return a})}function f(){return[{createWith:i,method:"GET"},{createWith:a,method:"PUT"},{createWith:u,method:"PATCH"},{createWith:c,method:"DELETE"}]}function l(){return[{createWith:s,method:"POST"},{createWith:d,method:"GET"}]}function h(e){D(e.route);var r=e.resource.url+"/"+e.item.id+e.route;Facade.backend.when(e.method,r).respond(function(r,n,t,o){t=JSON.parse(t||"{}");var i=Facade.findRoute(r,n),a=O(e.resource).find(e.item.id),u=i.getSpecialResponseOr(function(){return e.callback(t,a,o)});return W(u),u})}function p(e){var r=_.isRegExp(e.route)?e.route:e.resource.url+e.route;Facade.backend.when(e.method,r).respond(function(r,n,t,o){t=JSON.parse(t||"{}");var i=O(e.resource).getAll(),a=Facade.findRoute(r,n),u=a.getSpecialResponseOr(function(){return e.callback(t,i)});return W(u),u})}function m(e){var r=e.resource.url+e.route;Facade.backend.expect(e.method,r,v(e.expected)).respond(function(r,n,t,o){t=JSON.parse(t||"{}");var i=O(e.resource).getAll(),a=Facade.findRoute(r,n);a.hasSpecialResponse()||_.isFunction(e.callback)&&e.callback(t,i);var u=a.getSpecialResponseOr(function(){return[200,JSON.stringify(i),{},"OK"]});return u})}function w(e){if(e.route=e.route||"",_.isRegExp(e.route))e.regExp=e.route;else{var r=e.resource.url,n=e.item?r+"/"+e.item.id+e.route:r+e.route,t=[e.method,n].join(" ");e.fullRoute=t}H[e.resource.name][e.regExp||e.fullRoute]=F(e)}function g(e){j.push(e)}function v(e){function r(n,t,o){if(n[o])return n[o]===t||(console.log("Expected",o,"to equal",t,"in",n,"but it was",n[o]),!1);var i=_.filter(n,function(e){return _.isObject(e)}),a=n[o]===t;return i||a?_.some(i,function(e){return r(e,t,o)}):(console.log("Missing expectedKey",o,"in",nestedData,"should include",e),!1)}return function(n){var t=JSON.parse(n);return t?_.every(e,function(e,n){return r(t,e,n)}):(console.log("Unable to parse to JSON:",n),!1)}}function E(e){return e=e||{},{url:e.url,name:e.name,createDefault:e.createDefault,addItem:function(e){return x(e),O(this).create(e),z&&o(this,e),e},resource:function(e){return e.url=this.url+e.url,Facade.resource(e)},addRoute:function(e){if(e=e||{},K(e),e.resource=this,g(e),e.onItem){var r=O(this).getAll();_.each(r,function(r){e.item=r,h(e),w(e)})}else p(e),w(e)},expect:function(r,n){J(r),n=n||"";var t=this;return{"with":function(o){e={method:r,route:n,expected:o,resource:t},m(e)}}}}}function F(e){var r=[];return{fullRoute:e.fullRoute,regExp:e.regExp,method:e.method,nextResponse:function(e,n){r.push({status:e,data:n})},getSpecialResponse:function(){return r.shift()},hasSpecialResponse:function(){return Boolean(r.length)},getSpecialResponseOr:function(e){if(this.hasSpecialResponse()){var r=this.getSpecialResponse();return[r.status,JSON.stringify(r.data),{},"OK"]}return _.isFunction(e)&&e()}}}function S(e){var r={};return{getAll:function(){return _.map(r)},create:function(e){x(e);var n=e.id;r[JSON.stringify(n)]=e},find:function(n,t){N(n),t=t||{};var o=r[JSON.stringify(n)];if(!o)throw new Error("No item found in "+e+" table with id of "+n);return t.wrap?T(o,k(e)):o},"delete":function(n){N(n);var n=JSON.stringify(n),t=r[n];if(!t)throw new Error("No item found in "+e+" table with id of "+n+". So can't delete it.");return r[n]=null,t}}}function O(e){var r=Facade.db[e.name];if(!r)throw new Error("There doesnt appear to be a table called "+e.name);return r}function b(e){return O(e).getAll()}function R(e,r,n){return n=n||{},O(e).find(r,n)}function T(e,r){return e=_.extend({},e),e.showUrl=function(){return r.url+"/"+e.id},e}function k(e){var r=Facade.resources[e];if(!r)throw new Error("There doesnt appear to be a resource called "+e);return r}function y(e){if(!_.isString(e.name))throw new Error("You must provide a name for the resource");if(Facade.resources[e.name])throw new Error("A resource named "+e.name+" already exists. Please choose a different name.");if(!_.isString(e.url))throw new Error("You must provide a url for the "+e.name+" resource");var r=_.map(Facade.resources,"url");if(_.find(r,function(r){return r===e.url}))throw new Error("The url "+e.url+" is already taken. Please change one")}function x(e){if(!e.id)throw new Error("The resource must have an id property.")}function N(e){if(!e)throw new Error("You must pass in an id to find a record")}function J(e){if(!_.isString(e))throw new Error("No HTTP method was provided");var r=["GET","POST","PATCH","PUT","HEAD","DELETE"];if(!_.includes(r,e))throw new Error(e+" is not a valid HTTP method.")}function P(e){e=e||{};var r=e.backend||{};if(!_.isFunction(r.whenGET))throw new Error("$httpBackend not detected. You must add it when initializing, like Facade.initialize({backend: $httpBackend})")}function A(){z&&console.warn("Facade is already initialized. Generally this shouldn't happen. So everything will be cleared, and initialized again. Thus, you shouldn't rely on any data added before the first initialization.")}function D(e){if(_.isRegExp(e))throw new Error("Regex routes can't be used for item routes. Either make 'onItem' false or make the route a string")}function K(e){if(J(e.method),!_.isString(e.route)&&!_.isRegExp(e.route))throw new Error("You must supply a route (eg: '/my_route') as either a string or regex");if(!e.callback)throw new Error("You must supply a response callback for custom routes.")}function W(e){if(!_.isArray(e))throw new Error("Response must be an array");if(4!==e.length)throw new Error("Response does not appear to be in the form of [status, data, headers, status_text]")}window.Facade={};var G,z=!1;Facade.resources={},Facade.db={};var H={},Y={},I={},U={},j=[];Facade.resource=function(e){return e=e||{},y(e),this.db[e.name]=S(e.name),H[e.name]={},this.resources[e.name]=E(e)},Facade.initialize=function(n){A(),Facade.clear(),n=n||{},Facade.backend=n.backend,P(n),z=!0,_.isFunction(G)&&G(),_.each(this.resources,function(e){r(e)}),e()},Facade.reset=function(){Facade.resources=_.clone(Y,!0),Facade.db=_.clone(I,!0),H=_.clone(U,!0),z=!1},Facade.define=function(e){G=e},Facade.undefine=function(){G=void 0},Facade.clear=function(){this.resources={},this.db={},H={},j=[],this.backend=void 0,z=!1},Facade.findRoute=function(e,r){var n,t=[e,r].join(" "),o=_.some(H,function(o){return n=o[t],n?n:n=_.chain(o).filter("regExp").filter({method:e}).find(function(e){return e.regExp.test(r)}).value()});if(!o)throw new Error("The route "+t+" does not exist");return n}}).call(this);