Skip to content

Commit

Permalink
feat: update spyOnProperty method, fixes jestjs#5746
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasjinlo committed Mar 8, 2018
1 parent 3e82577 commit b3c1771
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
112 changes: 112 additions & 0 deletions packages/jest-mock/src/__tests__/jest_mock.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -830,5 +830,117 @@ describe('moduleMocker', () => {
expect(spy1.mock.calls.length).toBe(1);
expect(spy2.mock.calls.length).toBe(1);
});

it('should work with instance object - getter', () => {
let isOriginalCalled = false;
let originalCallThis;
let originalCallArguments;
class Constructor {
get method() {
return function() {
isOriginalCalled = true;
originalCallThis = this;
originalCallArguments = arguments;
};
}
}
const obj = new Constructor();

const spy = moduleMocker.spyOn(obj, 'method', 'get');

const thisArg = {this: true};
const firstArg = {first: true};
const secondArg = {second: true};
obj.method.call(thisArg, firstArg, secondArg);
expect(isOriginalCalled).toBe(true);
expect(originalCallThis).toBe(thisArg);
expect(originalCallArguments.length).toBe(2);
expect(originalCallArguments[0]).toBe(firstArg);
expect(originalCallArguments[1]).toBe(secondArg);
expect(spy).toHaveBeenCalled();

isOriginalCalled = false;
originalCallThis = null;
originalCallArguments = null;
spy.mockReset();
spy.mockRestore();
obj.method.call(thisArg, firstArg, secondArg);
expect(isOriginalCalled).toBe(true);
expect(originalCallThis).toBe(thisArg);
expect(originalCallArguments.length).toBe(2);
expect(originalCallArguments[0]).toBe(firstArg);
expect(originalCallArguments[1]).toBe(secondArg);
expect(spy).not.toHaveBeenCalled();
});

test('should work with instance object - setter', () => {
class Constructor {
constructor() {
this._property = false;
}

set property(value) {
this._property = value;
}

get property() {
return this._property;
}
}
const obj = new Constructor();

const spy = moduleMocker.spyOn(obj, 'property', 'set');
obj.property = true;
expect(spy).toHaveBeenCalled();
expect(obj.property).toBe(true);
obj.property = false;
spy.mockReset();
spy.mockRestore();
obj.property = true;
expect(spy).not.toHaveBeenCalled();
expect(obj.property).toBe(true);
});

it('supports restoring all spies on an instance object', () => {
let methodOneCalls = 0;
let methodTwoCalls = 0;
class Constructor {
get methodOne() {
return function() {
methodOneCalls++;
};
}

get methodTwo() {
return function() {
methodTwoCalls++;
};
}
}
const obj = new Constructor();

const spy1 = moduleMocker.spyOn(obj, 'methodOne', 'get');
const spy2 = moduleMocker.spyOn(obj, 'methodTwo', 'get');

// First, we call with the spies: both spies and both original functions
// should be called.
obj.methodOne();
obj.methodTwo();
expect(methodOneCalls).toBe(1);
expect(methodTwoCalls).toBe(1);
expect(spy1.mock.calls.length).toBe(1);
expect(spy2.mock.calls.length).toBe(1);

moduleMocker.restoreAllMocks();

// Then, after resetting all mocks, we call methods again. Only the real
// methods should bump their count, not the spies.
obj.methodOne();
obj.methodTwo();
expect(methodOneCalls).toBe(2);
expect(methodTwoCalls).toBe(2);
expect(spy1.mock.calls.length).toBe(1);
expect(spy2.mock.calls.length).toBe(1);
});
});
});
8 changes: 7 additions & 1 deletion packages/jest-mock/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,13 @@ class ModuleMockerClass {
throw new Error('No property name supplied');
}

const descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
let proto = Object.getPrototypeOf(obj);

while (!descriptor && proto !== null) {
descriptor = Object.getOwnPropertyDescriptor(proto, propertyName);
proto = Object.getPrototypeOf(proto);
}

if (!descriptor) {
throw new Error(propertyName + ' property does not exist');
Expand Down

0 comments on commit b3c1771

Please sign in to comment.