Skip to content

Commit

Permalink
fix(jest-mock): tweak typings to allow jest.replaceProperty() repla…
Browse files Browse the repository at this point in the history
…ce methods (#14008)
  • Loading branch information
mrazauskas committed Apr 9, 2023
1 parent 88cd2cf commit c40ef21
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
- `[jest-config]` Handle frozen config object ([#14054](https://github.com/facebook/jest/pull/14054))
- `[jest-environment-jsdom, jest-environment-node]` Fix assignment of `customExportConditions` via `testEnvironmentOptions` when custom env subclass defines a default value ([#13989](https://github.com/facebook/jest/pull/13989))
- `[jest-matcher-utils]` Fix copying value of inherited getters ([#14007](https://github.com/facebook/jest/pull/14007))
- `[jest-mock]` Tweak typings to allow `jest.replaceProperty()` replace methods ([#14008](https://github.com/facebook/jest/pull/14008))
- `[jest-snapshot]` Fix a potential bug when not using prettier and improve performance ([#14036](https://github.com/facebook/jest/pull/14036))
- `[@jest/transform]` Do not instrument `.json` modules ([#14048](https://github.com/facebook/jest/pull/14048))

Expand Down
23 changes: 14 additions & 9 deletions packages/jest-mock/__typetests__/mock-functions.test.ts
Expand Up @@ -497,20 +497,25 @@ expectError(

// replaceProperty + Replaced

const obj = {
fn: () => {},

const replaceObject = {
method: () => {},
property: 1,
};

expectType<Replaced<number>>(replaceProperty(obj, 'property', 1));
expectType<void>(replaceProperty(obj, 'property', 1).replaceValue(1).restore());
expectType<Replaced<number>>(replaceProperty(replaceObject, 'property', 1));
expectType<Replaced<() => void>>(
replaceProperty(replaceObject, 'method', () => {}),
);
expectType<void>(
replaceProperty(replaceObject, 'property', 1).replaceValue(1).restore(),
);

expectError(replaceProperty(obj, 'invalid', 1));
expectError(replaceProperty(obj, 'property', 'not a number'));
expectError(replaceProperty(obj, 'fn', () => {}));
expectError(replaceProperty(replaceObject, 'invalid', 1));
expectError(replaceProperty(replaceObject, 'property', 'not a number'));

expectError(replaceProperty(obj, 'property', 1).replaceValue('not a number'));
expectError(
replaceProperty(replaceObject, 'property', 1).replaceValue('not a number'),
);

interface ComplexObject {
numberOrUndefined: number | undefined;
Expand Down
24 changes: 10 additions & 14 deletions packages/jest-mock/src/index.ts
Expand Up @@ -177,17 +177,13 @@ export 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;
}

type ReplacedPropertyRestorer<
T extends object,
K extends PropertyLikeKeys<T>,
> = {
type ReplacedPropertyRestorer<T extends object, K extends keyof T> = {
(): void;
object: T;
property: K;
Expand Down Expand Up @@ -995,10 +991,10 @@ export class ModuleMocker {
/**
* Check whether the given property of an object has been already replaced.
*/
private _findReplacedProperty<
T extends object,
K extends PropertyLikeKeys<T>,
>(object: T, propertyKey: K): ReplacedPropertyRestorer<T, K> | undefined {
private _findReplacedProperty<T extends object, K extends keyof T>(
object: T,
propertyKey: K,
): ReplacedPropertyRestorer<T, K> | undefined {
for (const {restore} of this._spyState) {
if (
'object' in restore &&
Expand Down Expand Up @@ -1328,11 +1324,11 @@ export class ModuleMocker {
return descriptor[accessType] as Mock;
}

replaceProperty<
T extends object,
K extends PropertyLikeKeys<T>,
V extends T[K],
>(object: T, propertyKey: K, value: V): Replaced<T[K]> {
replaceProperty<T extends object, K extends keyof T>(
object: T,
propertyKey: K,
value: T[K],
): Replaced<T[K]> {
if (object === undefined || object == null) {
throw new Error(
`replaceProperty could not find an object on which to replace ${String(
Expand Down

0 comments on commit c40ef21

Please sign in to comment.