getJasmineRequireObj().SpyRegistry = function(j$) { function SpyRegistry(options) { options = options || {}; var currentSpies = options.currentSpies || function() { return []; }; this.spyOn = function(obj, methodName) { if (j$.util.isUndefined(obj)) { throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); } if (j$.util.isUndefined(methodName)) { throw new Error('No method name supplied'); } if (j$.util.isUndefined(obj[methodName])) { throw new Error(methodName + '() method does not exist'); } if (obj[methodName] && j$.isSpy(obj[methodName])) { //TODO?: should this return the current spy? Downside: may cause user confusion about spy state throw new Error(methodName + ' has already been spied upon'); } var descriptor; try { descriptor = Object.getOwnPropertyDescriptor(obj, methodName); } catch(e) { // IE 8 doesn't support `definePropery` on non-DOM nodes } if (descriptor && !(descriptor.writable || descriptor.set)) { throw new Error(methodName + ' is not declared writable or has no setter'); } var spy = j$.createSpy(methodName, obj[methodName]); currentSpies().push({ spy: spy, baseObj: obj, methodName: methodName, originalValue: obj[methodName] }); obj[methodName] = spy; return spy; }; this.clearSpies = function() { var spies = currentSpies(); for (var i = spies.length - 1; i >= 0; i--) { var spyEntry = spies[i]; spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; } }; } return SpyRegistry; };