1 |
|
2 | void function () {
|
3 | var _, _find, _registry, allStubs, bond, createAnonymousSpy, createReturnSpy, createThroughSpy, enhanceSpy, isFunction, nextTick, registerCleanupHook, registered, registry;
|
4 | _ = require('underscore');
|
5 | isFunction = function (obj) {
|
6 | return typeof obj === 'function';
|
7 | };
|
8 | createThroughSpy = function (getValue, bondApi) {
|
9 | var spy;
|
10 | spy = function () {
|
11 | var args, isConstructor, result;
|
12 | args = Array.prototype.slice.call(arguments);
|
13 | spy.calledArgs[spy.called] = args;
|
14 | spy.called++;
|
15 | result = getValue.apply(this, args);
|
16 | isConstructor = this instanceof arguments.callee;
|
17 | if (isConstructor && typeof result !== 'object')
|
18 | return this;
|
19 | return result;
|
20 | };
|
21 | return enhanceSpy(spy, getValue, bondApi);
|
22 | };
|
23 | createReturnSpy = function (getValue, bondApi) {
|
24 | var spy;
|
25 | spy = function () {
|
26 | var args;
|
27 | args = Array.prototype.slice.call(arguments);
|
28 | spy.calledArgs[spy.called] = args;
|
29 | spy.called++;
|
30 | return getValue.apply(this, args);
|
31 | };
|
32 | return enhanceSpy(spy, getValue, bondApi);
|
33 | };
|
34 | createAnonymousSpy = function () {
|
35 | var returnValue, spy;
|
36 | returnValue = null;
|
37 | spy = function () {
|
38 | var args;
|
39 | args = Array.prototype.slice.call(arguments);
|
40 | spy.calledArgs[spy.called] = args;
|
41 | spy.called++;
|
42 | return returnValue;
|
43 | };
|
44 | enhanceSpy(spy);
|
45 | spy['return'] = function (newReturnValue) {
|
46 | returnValue = newReturnValue;
|
47 | return spy;
|
48 | };
|
49 | return spy;
|
50 | };
|
51 | enhanceSpy = function (spy, original, bondApi) {
|
52 | var k, v;
|
53 | spy.prototype = null != original ? original.prototype : void 0;
|
54 | spy.called = 0;
|
55 | spy.calledArgs = [];
|
56 | spy.calledWith = function (args) {
|
57 | var calledArgs;
|
58 | args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
|
59 | for (var i$ = 0, length$ = spy.calledArgs.length; i$ < length$; ++i$) {
|
60 | calledArgs = spy.calledArgs[i$];
|
61 | if (_.isEqual(args, calledArgs))
|
62 | return true;
|
63 | }
|
64 | return false;
|
65 | };
|
66 | if (bondApi)
|
67 | for (k in bondApi) {
|
68 | v = bondApi[k];
|
69 | spy[k] = v;
|
70 | }
|
71 | return spy;
|
72 | };
|
73 | nextTick = function () {
|
74 | if (isFunction('undefined' !== typeof process && null != process ? process.nextTick : void 0))
|
75 | return process.nextTick;
|
76 | if ('undefined' !== typeof setImmediate && null != setImmediate && isFunction(setImmediate))
|
77 | return setImmediate;
|
78 | return function (fn) {
|
79 | return setTimeout(fn, 0);
|
80 | };
|
81 | }();
|
82 | _registry = [];
|
83 | _find = function (obj) {
|
84 | var store;
|
85 | for (var i$ = 0, length$ = _registry.length; i$ < length$; ++i$) {
|
86 | store = _registry[i$];
|
87 | if (store.obj === obj)
|
88 | return store;
|
89 | }
|
90 | store = {
|
91 | obj: obj,
|
92 | props: {}
|
93 | };
|
94 | _registry.push(store);
|
95 | return store;
|
96 | };
|
97 | registry = {
|
98 | set: function (obj, prop, value, newValue) {
|
99 | var store;
|
100 | store = _find(obj);
|
101 | if (!(null != store.props[prop]))
|
102 | return store.props[prop] = value;
|
103 | },
|
104 | get: function (obj, prop) {
|
105 | return _find(obj).props[prop];
|
106 | },
|
107 | restore: function (obj, prop) {
|
108 | return obj[prop] = _find(obj).props[prop];
|
109 | },
|
110 | restoreAll: function () {
|
111 | var prop, store, value;
|
112 | for (var i$ = 0, length$ = _registry.length; i$ < length$; ++i$) {
|
113 | store = _registry[i$];
|
114 | for (prop in store.props) {
|
115 | value = store.props[prop];
|
116 | store.obj[prop] = value;
|
117 | }
|
118 | }
|
119 | return _registry = [];
|
120 | }
|
121 | };
|
122 | allStubs = [];
|
123 | registered = false;
|
124 | registerCleanupHook = function () {
|
125 | var after;
|
126 | if (registered)
|
127 | return;
|
128 | after = 'undefined' !== typeof afterEach && null != afterEach ? afterEach : 'undefined' !== typeof testDone && null != testDone ? testDone : null != ('undefined' !== typeof QUnit && null != QUnit ? QUnit.testDone : void 0) ? 'undefined' !== typeof QUnit && null != QUnit ? QUnit.testDone : void 0 : null != bond.cleanup ? bond.cleanup : function () {
|
129 | throw new Error('bond.cleanup must be specified if your test runner does not use afterEach or testDone');
|
130 | };
|
131 | after(function () {
|
132 | return registry.restoreAll();
|
133 | });
|
134 | return registered = true;
|
135 | };
|
136 | bond = function (obj, property) {
|
137 | var asyncReturn, previous, registerRestore, restore, returnMethod, through, to;
|
138 | registerCleanupHook();
|
139 | if (arguments.length === 0)
|
140 | return createAnonymousSpy();
|
141 | previous = obj[property];
|
142 | registerRestore = function () {
|
143 | return registry.set(obj, property, previous);
|
144 | };
|
145 | restore = function () {
|
146 | return registry.restore(obj, property);
|
147 | };
|
148 | to = function (newValue) {
|
149 | registerRestore();
|
150 | if (isFunction(newValue))
|
151 | newValue = createThroughSpy(newValue, this);
|
152 | obj[property] = newValue;
|
153 | return obj[property];
|
154 | };
|
155 | returnMethod = function (returnValue) {
|
156 | var returnValueFn;
|
157 | registerRestore();
|
158 | returnValueFn = function () {
|
159 | return returnValue;
|
160 | };
|
161 | obj[property] = createReturnSpy(returnValueFn, this);
|
162 | return obj[property];
|
163 | };
|
164 | asyncReturn = function (returnValues) {
|
165 | returnValues = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
|
166 | return to(function (callback) {
|
167 | var numArgs$;
|
168 | var args;
|
169 | if ((numArgs$ = arguments.length) > 1) {
|
170 | args = [].slice.call(arguments, 0, numArgs$ - 1);
|
171 | callback = arguments[numArgs$ - 1];
|
172 | } else {
|
173 | args = [];
|
174 | }
|
175 | if (!isFunction(callback))
|
176 | throw new Error('asyncReturn expects last argument to be a function');
|
177 | return nextTick(function () {
|
178 | return callback.apply(null, [].slice.call(returnValues));
|
179 | });
|
180 | });
|
181 | };
|
182 | through = function () {
|
183 | registerRestore();
|
184 | obj[property] = createThroughSpy(previous, this);
|
185 | return obj[property];
|
186 | };
|
187 | return {
|
188 | to: to,
|
189 | 'return': returnMethod,
|
190 | asyncReturn: asyncReturn,
|
191 | through: through,
|
192 | restore: restore
|
193 | };
|
194 | };
|
195 | module.exports = bond;
|
196 | }.call(this);
|