jest-mock
Advanced tools
Comparing version 29.3.1 to 29.4.0
@@ -221,2 +221,3 @@ /** | ||
private _invocationCallCounter; | ||
private _originalFn; | ||
/** | ||
@@ -237,2 +238,6 @@ * @see README.md | ||
/** | ||
* Check whether the given property of an object has been already replaced. | ||
*/ | ||
private _findReplacedProperty; | ||
/** | ||
* @see README.md | ||
@@ -282,2 +287,7 @@ * @param metadata Metadata for the mock in the schema returned by the | ||
private _spyOnProperty; | ||
replaceProperty< | ||
T extends object, | ||
K extends PropertyLikeKeys<T>, | ||
V extends T[K], | ||
>(object: T, propertyKey: K, value: V): Replaced<T[K]>; | ||
clearAllMocks(): void; | ||
@@ -309,2 +319,33 @@ resetAllMocks(): void; | ||
export declare interface Replaced<T = unknown> { | ||
/** | ||
* Restore property to its original value known at the time of mocking. | ||
*/ | ||
restore(): void; | ||
/** | ||
* Change the value of the property. | ||
*/ | ||
replaceValue(value: T): this; | ||
} | ||
export declare const replaceProperty: < | ||
T extends object, | ||
K_2 extends Exclude< | ||
keyof T, | ||
| keyof { | ||
[K in keyof T as Required<T>[K] extends ClassLike ? K : never]: T[K]; | ||
} | ||
| keyof { | ||
[K_1 in keyof T as Required<T>[K_1] extends FunctionLike | ||
? K_1 | ||
: never]: T[K_1]; | ||
} | ||
>, | ||
V extends T[K_2], | ||
>( | ||
object: T, | ||
propertyKey: K_2, | ||
value: V, | ||
) => Replaced<T[K_2]>; | ||
declare type ResolveType<T extends FunctionLike> = | ||
@@ -311,0 +352,0 @@ ReturnType<T> extends PromiseLike<infer U> ? U : never; |
@@ -6,3 +6,8 @@ 'use strict'; | ||
}); | ||
exports.spyOn = exports.mocked = exports.fn = exports.ModuleMocker = void 0; | ||
exports.spyOn = | ||
exports.replaceProperty = | ||
exports.mocked = | ||
exports.fn = | ||
exports.ModuleMocker = | ||
void 0; | ||
function _jestUtil() { | ||
@@ -207,2 +212,3 @@ const data = require('jest-util'); | ||
_invocationCallCounter; | ||
_originalFn; | ||
@@ -220,2 +226,3 @@ /** | ||
this._invocationCallCounter = 1; | ||
this._originalFn = new WeakMap(); | ||
} | ||
@@ -426,3 +433,8 @@ _getSlots(object) { | ||
f.mockClear(); | ||
this._mockConfigRegistry.delete(f); | ||
const originalFn = this._originalFn.get(f); | ||
const originalMockImpl = { | ||
...this._defaultMockConfig(), | ||
mockImpl: originalFn | ||
}; | ||
this._mockConfigRegistry.set(f, originalMockImpl); | ||
return f; | ||
@@ -586,2 +598,19 @@ }; | ||
/** | ||
* Check whether the given property of an object has been already replaced. | ||
*/ | ||
_findReplacedProperty(object, propertyKey) { | ||
for (const spyState of this._spyState) { | ||
if ( | ||
'object' in spyState && | ||
'property' in spyState && | ||
spyState.object === object && | ||
spyState.property === propertyKey | ||
) { | ||
return spyState; | ||
} | ||
} | ||
return; | ||
} | ||
/** | ||
* @see README.md | ||
@@ -683,3 +712,3 @@ * @param metadata Metadata for the mock in the schema returned by the | ||
throw new Error( | ||
`Cannot spyOn on a primitive value; ${this._typeOf(object)} given` | ||
`Cannot use spyOn on a primitive value; ${this._typeOf(object)} given` | ||
); | ||
@@ -689,3 +718,3 @@ } | ||
throw new Error( | ||
`spyOn could not find an object to spy upon for ${String(methodKey)}` | ||
`spyOn could not find an object to spy on for ${String(methodKey)}` | ||
); | ||
@@ -703,7 +732,13 @@ } | ||
throw new Error( | ||
`Cannot spy the ${String( | ||
`Cannot spy on the ${String( | ||
methodKey | ||
)} property because it is not a function; ${this._typeOf( | ||
original | ||
)} given instead` | ||
)} given instead.${ | ||
typeof original !== 'object' | ||
? ` If you are trying to mock a property, use \`jest.replaceProperty(object, '${String( | ||
methodKey | ||
)}', value)\` instead.` | ||
: '' | ||
}` | ||
); | ||
@@ -755,2 +790,3 @@ } | ||
} | ||
this._originalFn.set(object[methodKey], original); | ||
return object[methodKey]; | ||
@@ -782,7 +818,13 @@ } | ||
throw new Error( | ||
`Cannot spy the ${String( | ||
`Cannot spy on the ${String( | ||
propertyKey | ||
)} property because it is not a function; ${this._typeOf( | ||
original | ||
)} given instead` | ||
)} given instead.${ | ||
typeof original !== 'object' | ||
? ` If you are trying to mock a property, use \`jest.replaceProperty(object, '${String( | ||
propertyKey | ||
)}', value)\` instead.` | ||
: '' | ||
}` | ||
); | ||
@@ -808,2 +850,91 @@ } | ||
} | ||
replaceProperty(object, propertyKey, value) { | ||
if (object === undefined || object == null) { | ||
throw new Error( | ||
`replaceProperty could not find an object on which to replace ${String( | ||
propertyKey | ||
)}` | ||
); | ||
} | ||
if (propertyKey === undefined || propertyKey === null) { | ||
throw new Error('No property name supplied'); | ||
} | ||
if (typeof object !== 'object') { | ||
throw new Error( | ||
`Cannot mock property on a non-object value; ${this._typeOf( | ||
object | ||
)} given` | ||
); | ||
} | ||
let descriptor = Object.getOwnPropertyDescriptor(object, propertyKey); | ||
let proto = Object.getPrototypeOf(object); | ||
while (!descriptor && proto !== null) { | ||
descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey); | ||
proto = Object.getPrototypeOf(proto); | ||
} | ||
if (!descriptor) { | ||
throw new Error(`${String(propertyKey)} property does not exist`); | ||
} | ||
if (!descriptor.configurable) { | ||
throw new Error(`${String(propertyKey)} is not declared configurable`); | ||
} | ||
if (descriptor.get !== undefined) { | ||
throw new Error( | ||
`Cannot mock the ${String( | ||
propertyKey | ||
)} property because it has a getter. Use \`jest.spyOn(object, '${String( | ||
propertyKey | ||
)}', 'get').mockReturnValue(value)\` instead.` | ||
); | ||
} | ||
if (descriptor.set !== undefined) { | ||
throw new Error( | ||
`Cannot mock the ${String( | ||
propertyKey | ||
)} property because it has a setter. Use \`jest.spyOn(object, '${String( | ||
propertyKey | ||
)}', 'set').mockReturnValue(value)\` instead.` | ||
); | ||
} | ||
if (typeof descriptor.value === 'function') { | ||
throw new Error( | ||
`Cannot mock the ${String( | ||
propertyKey | ||
)} property because it is a function. Use \`jest.spyOn(object, '${String( | ||
propertyKey | ||
)}')\` instead.` | ||
); | ||
} | ||
const existingRestore = this._findReplacedProperty(object, propertyKey); | ||
if (existingRestore) { | ||
return existingRestore.replaced.replaceValue(value); | ||
} | ||
const isPropertyOwner = Object.prototype.hasOwnProperty.call( | ||
object, | ||
propertyKey | ||
); | ||
const originalValue = descriptor.value; | ||
const restore = () => { | ||
if (isPropertyOwner) { | ||
object[propertyKey] = originalValue; | ||
} else { | ||
delete object[propertyKey]; | ||
} | ||
}; | ||
const replaced = { | ||
replaceValue: value => { | ||
object[propertyKey] = value; | ||
return replaced; | ||
}, | ||
restore: () => { | ||
restore(); | ||
this._spyState.delete(restore); | ||
} | ||
}; | ||
restore.object = object; | ||
restore.property = propertyKey; | ||
restore.replaced = replaced; | ||
this._spyState.add(restore); | ||
return replaced.replaceValue(value); | ||
} | ||
clearAllMocks() { | ||
@@ -813,2 +944,3 @@ this._mockState = new WeakMap(); | ||
resetAllMocks() { | ||
this._spyState.forEach(reset => reset()); | ||
this._mockConfigRegistry = new WeakMap(); | ||
@@ -836,1 +968,3 @@ this._mockState = new WeakMap(); | ||
exports.mocked = mocked; | ||
const replaceProperty = JestMock.replaceProperty.bind(JestMock); | ||
exports.replaceProperty = replaceProperty; |
{ | ||
"name": "jest-mock", | ||
"version": "29.3.1", | ||
"version": "29.4.0", | ||
"repository": { | ||
@@ -20,8 +20,8 @@ "type": "git", | ||
"dependencies": { | ||
"@jest/types": "^29.3.1", | ||
"@jest/types": "^29.4.0", | ||
"@types/node": "*", | ||
"jest-util": "^29.3.1" | ||
"jest-util": "^29.4.0" | ||
}, | ||
"devDependencies": { | ||
"@tsd/typescript": "~4.8.2", | ||
"@tsd/typescript": "^4.9.0", | ||
"tsd-lite": "^0.6.0" | ||
@@ -35,3 +35,3 @@ }, | ||
}, | ||
"gitHead": "05deb8393c4ad71e19be2567b704dfd3a2ab5fc9" | ||
"gitHead": "4bc0e8acaf990e6618a7bed1dca67760c20bb12a" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
90820
6
1324
Updated@jest/types@^29.4.0
Updatedjest-util@^29.4.0