mirror of
https://github.com/sstent/alex_app1.git
synced 2026-01-26 09:02:38 +00:00
185 lines
4.6 KiB
JavaScript
185 lines
4.6 KiB
JavaScript
var path = require('path');
|
|
|
|
function Gently() {
|
|
this.expectations = [];
|
|
this.hijacked = {};
|
|
|
|
var self = this;
|
|
process.addListener('exit', function() {
|
|
self.verify('process exit');
|
|
});
|
|
};
|
|
module.exports = Gently;
|
|
|
|
Gently.prototype.stub = function(location, exportsName) {
|
|
function Stub() {
|
|
return Stub['new'].apply(this, arguments);
|
|
};
|
|
|
|
Stub['new'] = function () {};
|
|
|
|
var stubName = 'require('+JSON.stringify(location)+')';
|
|
if (exportsName) {
|
|
stubName += '.'+exportsName;
|
|
}
|
|
|
|
Stub.prototype.toString = Stub.toString = function() {
|
|
return stubName;
|
|
};
|
|
|
|
var exports = this.hijacked[location] || {};
|
|
if (exportsName) {
|
|
exports[exportsName] = Stub;
|
|
} else {
|
|
exports = Stub;
|
|
}
|
|
|
|
this.hijacked[location] = exports;
|
|
return Stub;
|
|
};
|
|
|
|
Gently.prototype.hijack = function(realRequire) {
|
|
var self = this;
|
|
return function(location) {
|
|
return self.hijacked[location] = (self.hijacked[location])
|
|
? self.hijacked[location]
|
|
: realRequire(location);
|
|
};
|
|
};
|
|
|
|
Gently.prototype.expect = function(obj, method, count, stubFn) {
|
|
if (typeof obj != 'function' && typeof obj != 'object' && typeof obj != 'number') {
|
|
throw new Error
|
|
( 'Bad 1st argument for gently.expect(), '
|
|
+ 'object, function, or number expected, got: '+(typeof obj)
|
|
);
|
|
} else if (typeof obj == 'function' && (typeof method != 'string')) {
|
|
// expect(stubFn) interface
|
|
stubFn = obj;
|
|
obj = null;
|
|
method = null;
|
|
count = 1;
|
|
} else if (typeof method == 'function') {
|
|
// expect(count, stubFn) interface
|
|
count = obj;
|
|
stubFn = method;
|
|
obj = null;
|
|
method = null;
|
|
} else if (typeof count == 'function') {
|
|
// expect(obj, method, stubFn) interface
|
|
stubFn = count;
|
|
count = 1;
|
|
} else if (count === undefined) {
|
|
// expect(obj, method) interface
|
|
count = 1;
|
|
}
|
|
|
|
var name = this._name(obj, method, stubFn);
|
|
this.expectations.push({obj: obj, method: method, stubFn: stubFn, name: name, count: count});
|
|
|
|
var self = this;
|
|
function delegate() {
|
|
return self._stubFn(this, obj, method, name, Array.prototype.slice.call(arguments));
|
|
}
|
|
|
|
if (!obj) {
|
|
return delegate;
|
|
}
|
|
|
|
var original = (obj[method])
|
|
? obj[method]._original || obj[method]
|
|
: undefined;
|
|
|
|
obj[method] = delegate;
|
|
return obj[method]._original = original;
|
|
};
|
|
|
|
Gently.prototype.restore = function(obj, method) {
|
|
if (!obj[method] || !obj[method]._original) {
|
|
throw new Error(this._name(obj, method)+' is not gently stubbed');
|
|
}
|
|
obj[method] = obj[method]._original;
|
|
};
|
|
|
|
Gently.prototype.verify = function(msg) {
|
|
if (!this.expectations.length) {
|
|
return;
|
|
}
|
|
|
|
var validExpectations = [];
|
|
for (var i = 0, l = this.expectations.length; i < l; i++) {
|
|
var expectation = this.expectations[i];
|
|
|
|
if (expectation.count > 0) {
|
|
validExpectations.push(expectation);
|
|
}
|
|
}
|
|
|
|
this.expectations = []; // reset so that no duplicate verification attempts are made
|
|
|
|
if (!validExpectations.length) {
|
|
return;
|
|
}
|
|
|
|
var expectation = validExpectations[0];
|
|
|
|
throw new Error
|
|
( 'Expected call to '+expectation.name+' did not happen'
|
|
+ ( (msg)
|
|
? ' ('+msg+')'
|
|
: ''
|
|
)
|
|
);
|
|
};
|
|
|
|
Gently.prototype._stubFn = function(self, obj, method, name, args) {
|
|
var expectation = this.expectations[0], obj, method;
|
|
|
|
if (!expectation) {
|
|
throw new Error('Unexpected call to '+name+', no call was expected');
|
|
}
|
|
|
|
if (expectation.obj !== obj || expectation.method !== method) {
|
|
throw new Error('Unexpected call to '+name+', expected call to '+ expectation.name);
|
|
}
|
|
|
|
expectation.count -= 1;
|
|
if (expectation.count === 0) {
|
|
this.expectations.shift();
|
|
|
|
// autorestore original if its not a closure
|
|
// and no more expectations on that object
|
|
var has_more_expectations = this.expectations.reduce(function (memo, expectation) {
|
|
return memo || (expectation.obj === obj && expectation.method === method);
|
|
}, false);
|
|
if (obj !== null && method !== null && !has_more_expectations) {
|
|
if (typeof obj[method]._original !== 'undefined') {
|
|
obj[method] = obj[method]._original;
|
|
delete obj[method]._original;
|
|
} else {
|
|
delete obj[method];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (expectation.stubFn) {
|
|
return expectation.stubFn.apply(self, args);
|
|
}
|
|
};
|
|
|
|
Gently.prototype._name = function(obj, method, stubFn) {
|
|
if (obj) {
|
|
var objectName = obj.toString();
|
|
if (objectName == '[object Object]' && obj.constructor.name) {
|
|
objectName = '['+obj.constructor.name+']';
|
|
}
|
|
return (objectName)+'.'+method+'()';
|
|
}
|
|
|
|
if (stubFn.name) {
|
|
return stubFn.name+'()';
|
|
}
|
|
|
|
return '>> '+stubFn.toString()+' <<';
|
|
};
|