Merge branch 'spyOnProperty2' of https://github.com/celluj34/jasmine into celluj34-spyOnProperty2
- Merges #1203 from @celluj34 - Merges #1008 from @smacker - Fixes #943
This commit is contained in:
@@ -288,6 +288,10 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return spyRegistry.spyOn.apply(spyRegistry, arguments);
|
||||
};
|
||||
|
||||
this.spyOnProperty = function() {
|
||||
return spyRegistry.spyOnProperty.apply(spyRegistry, arguments);
|
||||
};
|
||||
|
||||
var suiteFactory = function(description) {
|
||||
var suite = new j$.Suite({
|
||||
env: self,
|
||||
|
||||
@@ -68,6 +68,66 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
return spiedMethod;
|
||||
};
|
||||
|
||||
this.spyOnProperty = function (obj, propertyName, accessType) {
|
||||
accessType = accessType || 'get';
|
||||
|
||||
if (j$.util.isUndefined(obj)) {
|
||||
throw new Error('spyOn could not find an object to spy upon for ' + propertyName + '');
|
||||
}
|
||||
|
||||
if (j$.util.isUndefined(propertyName)) {
|
||||
throw new Error('No property name supplied');
|
||||
}
|
||||
|
||||
var descriptor;
|
||||
try {
|
||||
descriptor = j$.util.getPropertyDescriptor(obj, propertyName);
|
||||
} catch(e) {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
}
|
||||
|
||||
if (!descriptor) {
|
||||
throw new Error(propertyName + ' property does not exist');
|
||||
}
|
||||
|
||||
if (!descriptor.configurable) {
|
||||
throw new Error(propertyName + ' is not declared configurable');
|
||||
}
|
||||
|
||||
if(!descriptor[accessType]) {
|
||||
throw new Error('Property ' + propertyName + ' does not have access type ' + accessType);
|
||||
}
|
||||
|
||||
if (j$.isSpy(descriptor[accessType])) {
|
||||
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
|
||||
throw new Error(propertyName + ' has already been spied upon');
|
||||
}
|
||||
|
||||
var originalDescriptor = j$.util.clone(descriptor),
|
||||
spy = j$.createSpy(propertyName, descriptor[accessType]),
|
||||
restoreStrategy;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(obj, propertyName)) {
|
||||
restoreStrategy = function() {
|
||||
Object.defineProperty(obj, propertyName, originalDescriptor);
|
||||
};
|
||||
} else {
|
||||
restoreStrategy = function() {
|
||||
delete obj[propertyName];
|
||||
};
|
||||
}
|
||||
|
||||
currentSpies().push({
|
||||
restoreObjectToOriginalState: restoreStrategy
|
||||
});
|
||||
|
||||
descriptor[accessType] = spy;
|
||||
|
||||
Object.defineProperty(obj, propertyName, descriptor);
|
||||
|
||||
return spy;
|
||||
};
|
||||
|
||||
this.clearSpies = function() {
|
||||
var spies = currentSpies();
|
||||
for (var i = spies.length - 1; i >= 0; i--) {
|
||||
|
||||
@@ -56,6 +56,10 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
return env.spyOn(obj, methodName);
|
||||
},
|
||||
|
||||
spyOnProperty: function(obj, methodName, accessType) {
|
||||
return env.spyOnProperty(obj, methodName, accessType);
|
||||
},
|
||||
|
||||
jsApiReporter: new jasmine.JsApiReporter({
|
||||
timer: new jasmine.Timer()
|
||||
}),
|
||||
|
||||
@@ -55,5 +55,17 @@ getJasmineRequireObj().util = function() {
|
||||
return cloned;
|
||||
};
|
||||
|
||||
util.getPropertyDescriptor = function(obj, methodName) {
|
||||
var descriptor,
|
||||
proto = obj;
|
||||
|
||||
do {
|
||||
descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
} while (!descriptor && proto);
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
|
||||
return util;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user