Permalink
Browse files

Major refactor

pretendr objectsand template objects look the same, so I've made them the
same thing, and generating from a template is actually just cloning. This
has broken templates having their attributes copied deeply, and magic
primitive stuff, so that needs fixing
  • Loading branch information...
1 parent 5e3ba3f commit b7ff337f16f167685ec6d8b2d4f00b78676ddb9c @nathanmacinnes committed Aug 3, 2012
Showing with 114 additions and 226 deletions.
  1. +107 −219 lib/pretendr.js
  2. +7 −7 test/spec.js
View
@@ -2,253 +2,141 @@
"use strict";
-var enumerate, // fn - whether to enumerate the properties and recurse
+var nonPrimitive, // fn - whether to enumerate the properties and recurse
makeTemplate, // fn - get a template object
+ makeBaseObj,
+ makeMock,
pretendr, // fn - called by module.exports
- templateIns = [], // list of template inputs
- templateOuts = []; // template outputs they match to prevent infinit loops
+ pretendrFunction,
+ templateIns = [], // list of template inputs
+ templateOuts = []; // template outputs they match to prevent infinit loops
// Return whether the object passed in is of type 'object' or 'function'
// This is important, because string types cause infinite recursion and other
// types don't make much sense
-enumerate = function (o) {
+nonPrimitive = function (o) {
return typeof o === 'object' || typeof o === 'function';
};
-// Return a template object based on the given template descriptor, so that
-// pretendr objects can be created with returnValue et al already set
-makeTemplate = function (t) {
- var fake,
- i,
- index,
- ins,
- outs,
- ownTemplate,
- returnValue,
- setFake,
- setReturnValue,
- setTemplate,
- subTemplate,
- templateObj;
- for (i = 0; i < templateIns.length; i++) {
- if (templateIns[i] === t) {
- return templateOuts[i];
- }
- }
-
- templateIns.push(t);
- index = templateIns.length - 1;
-
- setReturnValue = function (val) {
- returnValue = val;
- };
- setFake = function (fn) {
- fake = fn;
- };
- setTemplate = function (tem) {
- ownTemplate = tem;
- };
- templateObj = {
- generate : function (o) {
- var i,
- p;
- p = this.apply(pretendr(t, o));
- return p;
- },
- apply : function (p) {
- var i;
- if (returnValue !== undefined) {
- p.returnValue(returnValue);
+makeBaseObj = function (descriptor, mock) {
+ var ins = [],
+ outs = [],
+ subMakeBaseObj;
+
+ subMakeBaseObj = function (descriptor, mock) {
+ var attributes = {},
+ baseObj = {},
+ makeCopy,
+ i,
+ indexNum,
+ setFake,
+ setReturnValue,
+ setTemplate;
+
+ for (i = 0; i < ins.length; i++) {
+ if (descriptor === ins[i]) {
+ return outs[i];
}
- if (fake !== undefined) {
- p.fake(fake);
+ }
+ indexNum = ins.length;
+ ins.push(descriptor);
+ outs[indexNum] = baseObj;
+
+ setFake = function (fake) {
+ attributes.fake = fake;
+ };
+ setReturnValue = function (value) {
+ attributes.returnValue = value;
+ };
+ setTemplate = function (desc) {
+ attributes.template = makeBaseObj(desc);
+ return attributes.template;
+ };
+ makeCopy = function (obj) {
+ var copy = makeBaseObj(descriptor, obj);
+ if (attributes.hasOwnProperty('fake')) {
+ copy.fake(attributes.fake);
}
- if (ownTemplate !== undefined) {
- p.template(ownTemplate);
+ if (attributes.hasOwnProperty('returnValue')) {
+ copy.returnValue(attributes.returnValue);
}
- for (i in t) {
- if (t.hasOwnProperty(i) && templateObj[i]) {
- templateObj[i].apply(p[i]);
+ if (attributes.hasOwnProperty('template')) {
+ copy.template(attributes.template.mock);
+ }
+ return copy;
+ };
+ if (typeof descriptor === 'function') {
+ baseObj.fake = setFake;
+ baseObj.returnValue = setReturnValue;
+ baseObj.template = setTemplate;
+ }
+ baseObj.clone = makeCopy;
+ baseObj.mock = mock || makeMock(descriptor, baseObj, attributes);
+ if (nonPrimitive(descriptor)) {
+ for (i in descriptor) {
+ if (descriptor.hasOwnProperty(i)) {
+ baseObj[i] = subMakeBaseObj(descriptor[i]);
+ baseObj.mock[i] = baseObj[i].mock;
}
}
- return p;
}
+ return baseObj;
};
- if (typeof t === 'function') {
- templateObj.returnValue = setReturnValue;
- templateObj.fake = setFake;
- templateObj.template = setTemplate;
+ return subMakeBaseObj(descriptor, mock);
+};
+
+makeMock = function (desc, base, attr) {
+ if (desc instanceof Array) {
+ return [];
}
- for (i in t) {
- if (t.hasOwnProperty(i) && enumerate(t[i])) {
- templateObj[i] = makeTemplate(t[i]);
- }
+ if (typeof desc === 'object') {
+ return {};
+ }
+ if (typeof desc === 'function') {
+ return pretendrFunction(attr, base);
}
- templateOuts[index] = templateObj;
- return templateObj;
+ return desc;
};
-// Create a pretendr object. If the optional second argument is provided, that
-// object will be used as the mock object. This is to aid with instances of
-// mock constructor functions.
-pretendr = function (o, f) {
- var ins = [], // objects which have been passed in to the pretendr function
- outs = [], // objects which have been returned by pretendr
- pretendr, // inner fn so that ins and outs aren't recreated by recursion
- pretendrFunction, // fn for creating mock functions
- pretendrPrimitive; // fn for creating mock primitives
-
- // an inner function is used so that ins and outs are created once per
- // external call, then resued to prevent infinite recursion
- pretendr = function (input, forced) {
- var i,
- indexNumber,
- mock,
- output;
-
- // loop through all objects which have been passed in before. If this
- // matches, return the corresponding out[], so that we don't get
- // infinite recursion
- for (i = 0; i < ins.length; i++) {
- if (input === ins[i]) {
- return outs[i];
+pretendrFunction = function (attributes, baseObject) {
+ var fn;
+ baseObject.calls = [];
+ baseObject.instances = [];
+ fn = function () {
+ var call = {},
+ instance,
+ i;
+ baseObject.calls.push(call);
+ call.args = arguments;
+ call.context = this;
+
+ for (i = 0; i < arguments.length; i++) {
+ if (typeof arguments[i] === 'function') {
+ call.callback = arguments[i];
}
}
- // otherwise, put in the input and store the number
- ins.push(input);
- indexNumber = ins.length - 1;
-
- // We want to recurse through objects and functions, so do them
- // separately
- if (enumerate(input)) {
- if (typeof input === 'function') {
- output = pretendrFunction();
- } else {
-
- // if an object has been passed that should be used as a basis
- // for the mock. Used when creating instances of templates.
- if (forced) {
- mock = forced;
-
- // if it's an array, we want the mock to be an array too
- } else if (input instanceof Array) {
- mock = [];
- } else {
- mock = {};
- }
-
- output = {
- mock : mock
- };
- }
-
- // Store the output before we recurse, so that it can be returned
- // if we come across the same input again
- outs[indexNumber] = output;
-
- // Loop through and recurse if necessary
- for (i in input) {
- if (input.hasOwnProperty(i)) {
- if (enumerate(input[i])) {
- output[i] = pretendr(input[i]);
- output.mock[i] = output[i].mock;
- } else {
-
- // primitive objects must be processed separately so
- // that they can have getter and setter functions
- output[i] = pretendrPrimitive(input[i], output.mock, i);
- }
- }
- }
- return output;
+ if (attributes.hasOwnProperty('returnValue')) {
+ call.returned = attributes.returnValue;
}
- return pretendrPrimitive(input);
- };
-
- // Base objects of mocked functions must have several methods, and the mocks
- // themselves must of course be functions, so do these in their own function
- pretendrFunction = function () {
- var fake,
- pretendrObj,
- returnValue,
- template;
- pretendrObj = {
- calls : [],
- instances : [],
- returnValue : function (r) {
- returnValue = r;
- },
- fake : function (fn) {
- fake = fn;
- },
- template : function (t) {
- template = makeTemplate(t);
- return template;
- },
- mock : function () {
- var call,
- i;
- call = {
- args : arguments,
- context : this
- };
- for (i = 0; i < arguments.length; i++) {
- if (typeof arguments[i] === 'function') {
- call.callback = arguments[i];
- }
- }
- pretendrObj.calls.push(call);
- if (this instanceof pretendrObj.mock) {
- if (!template) {
- template = pretendrObj.template();
- }
- pretendrObj.instances.push(template.generate(this));
- } else if (fake) {
- call.returned = fake.apply(this, arguments);
- } else if (template) {
- call.pretendr = template.generate();
- call.returned = call.pretendr.mock;
- } else {
- call.returned = returnValue;
- }
- return call.returned;
+ if (attributes.hasOwnProperty('fake')) {
+ call.returned = attributes.fake.apply(this, arguments);
+ }
+ if (this instanceof fn) {
+ if (!attributes.hasOwnProperty('template')) {
+ baseObject.template();
}
- };
- return pretendrObj;
- };
-
- // Primitives must have getters and setters so that we can record what
- // happens to them, so these are processed in their own functions too.
- pretendrPrimitive = function (val, parent, property) {
- var get,
- pretendrObj,
- set;
- pretendrObj = parent || {};
- get = function () {
- this.gets = this.gets + 1;
- return val;
- };
- set = function (v) {
- val = v;
- this.values.push(v);
- };
- if (Object.defineProperty) {
- pretendrObj.gets = 0;
- pretendrObj.values = [];
- Object.defineProperty(pretendrObj, property || 'mock', {
- get : get,
- set : set
- });
- } else {
- pretendrObj.mock = val;
+ instance = attributes.template.clone(this);
+ baseObject.instances.push(instance);
+ } else if (attributes.hasOwnProperty('template')) {
+ call.pretendr = attributes.template.clone();
+ call.returned = call.pretendr.mock;
}
- return pretendrObj;
+ return call.returned;
};
-
- return pretendr(o, f);
+ return fn;
};
// hide the extra arg of pretendr from the public
module.exports = function (o) {
- return pretendr(o);
+ return makeBaseObj(o);
};
Oops, something went wrong.

0 comments on commit b7ff337

Please sign in to comment.