@remotex-labs/xjet 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,11 +4,9 @@
4
4
  * DO NOT EDIT MANUALLY.
5
5
  */
6
6
  import type { xExpect } from '@remotex-labs/xjet-expect';
7
- import type { ConstructorLikeType, FunctionLikeType } from '@remotex-labs/xjet-expect';
8
- import type { FunctionLikeType, RejectedValueType, ResolvedValueType } from '@remotex-labs/xjet-expect';
9
- import type { ConstructorLikeType, FunctionType } from '@remotex-labs/xjet-expect';
10
- import type { ConstructorType } from '@remotex-labs/xjet-expect';
7
+ import type { FunctionLikeType, FunctionType } from '@remotex-labs/xjet-expect';
11
8
  import type { FunctionType } from '@remotex-labs/xjet-expect';
9
+ import type { FunctionType, RejectedValueType, ResolvedValueType } from '@remotex-labs/xjet-expect';
12
10
  import type { ContextType } from '@remotex-labs/xjet-expect';
13
11
  import type { FunctionLikeType } from '@remotex-labs/xjet-expect';
14
12
  import type { ContextType, FunctionType } from '@remotex-labs/xjet-expect';
@@ -76,41 +74,6 @@ export {};
76
74
  /**
77
75
  * Imports
78
76
  */
79
- /**
80
- * Finds the parent object and name of a given function or value in the global scope.
81
- *
82
- * @param fn - The function or value to find in the global scope
83
- * @returns An object containing the name and parent object of the function, or `undefined` if not found
84
- *
85
- * @remarks
86
- * The `getParentObject` function attempts to locate where a function or value is defined
87
- * within the global context (`globalThis`). It searches for the function's name in the
88
- * global scope and also within properties of global objects. This is useful for
89
- * determining the original location of a function or value in the global namespace.
90
- *
91
- * Responsibilities:
92
- * - Finding functions directly attached to `globalThis`
93
- * - Locating functions within objects in the global scope
94
- * - Identifying functions by reference equality with global properties
95
- * - Supporting both named and anonymous functions
96
- *
97
- * @example
98
- * ```ts
99
- * // Finding a global function
100
- * const result = getParentObject(setTimeout);
101
- * // Returns: { name: 'setTimeout', parent: globalThis }
102
- *
103
- * // Finding a method on a global object
104
- * const arrayResult = getParentObject(Array.prototype.map);
105
- * // Returns: { name: 'map', parent: Array.prototype }
106
- * ```
107
- *
108
- * @since 1.2.0
109
- */
110
- declare function getParentObject(fn: unknown): {
111
- name: string;
112
- object: Record<string, unknown>;
113
- } | undefined;
114
77
  /**
115
78
  * Creates a mock for an object property using property descriptors.
116
79
  *
@@ -148,8 +111,8 @@ declare function mockDescriptorProperty<T extends object>(target: T, key: string
148
111
  * Creates a mock function interface with the specified implementation and optional restore function.
149
112
  *
150
113
  * @template ReturnType - The return type of the mocked function.
151
- * @template Context - The context type that the mocked function binds to.
152
114
  * @template Args - The argument type of the mocked function. Defaults to an array of unknown values.
115
+ * @template Context - The context type that the mocked function binds to.
153
116
  *
154
117
  * @param implementation - An optional implementation of the mocked function.
155
118
  * @param restore - An optional restore function used to reset the mock.
@@ -162,7 +125,7 @@ declare function mockDescriptorProperty<T extends object>(target: T, key: string
162
125
  * Responsibilities:
163
126
  * - Creating mock functions with custom implementations
164
127
  * - Supporting restore functionality for resetting mocks
165
- * - Providing type-safe mock interfaces via {@link FnMockInterface}
128
+ * - Providing type-safe mock interfaces via {@link MockableFunctionInterface}
166
129
  * - Integrating with the {@link MockState} system
167
130
  *
168
131
  * @example
@@ -177,61 +140,80 @@ declare function mockDescriptorProperty<T extends object>(target: T, key: string
177
140
  * ```
178
141
  *
179
142
  * @see MockState
180
- * @see FnMockInterface
143
+ * @see MockableFunctionInterface
181
144
  * @see FunctionLikeType
182
145
  *
183
146
  * @since 1.2.0
184
147
  */
185
- declare function fnImplementation<ReturnType, Args extends Array<unknown>, Context>(implementation?: FunctionLikeType<ReturnType, Args, Context>, restore?: () => FunctionLikeType<ReturnType, Args, Context> | void): FnMockInterface<ReturnType, Args, Context>;
148
+ declare function fnImplementation<ReturnType, Args extends Array<unknown>, Context>(implementation?: FunctionLikeType<ReturnType, Args, Context>, restore?: () => FunctionLikeType<ReturnType, Args, Context> | void): MockableFunctionInterface<FunctionLikeType<ReturnType, Args, Context>>;
186
149
  /**
187
- * Creates a mock function with an optional custom implementation.
150
+ * Creates a mock implementation of the provided class constructor.
188
151
  *
189
- * @template Method - The return type of the function being mocked
190
- * @template Args - The argument types for the function, defaulting to unknown array
191
- * @template Context - The context type (`this`) for the function, defaulting to unknown
152
+ * @param method - The class constructor to mock
153
+ * @param implementation - Optional custom implementation of the mocked constructor
154
+ * @returns The mock state associated with the mocked constructor
192
155
  *
193
- * @param method - The original function to mock
194
- * @param implementation - Optional custom implementation to use instead of the original
195
- * @returns A {@link MockState} instance that wraps the original function
156
+ * @remarks
157
+ * This overload of the mockImplementation function is specifically designed for mocking class constructors.
158
+ * It allows for replacing a class implementation during testing while tracking instantiation.
159
+ *
160
+ * The implementation function can return a partial instance of the class, which will be used
161
+ * as the constructed object when the mock is called with 'new'.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * class User {
166
+ * name: string;
167
+ * age: number;
168
+ * constructor (name: string, age: number) {
169
+ * this.name = name;
170
+ * this.age = age;
171
+ * }
172
+ * }
173
+ *
174
+ * const MockUser = mockImplementation(User, (name, age) => ({ name, age: age + 1 }));
175
+ * const user = new MockUser('Alice', 30); // user.age === 31
176
+ * MockUser.verify.called(); // passes
177
+ * ```
178
+ *
179
+ * @since 1.2.2
180
+ */
181
+ declare function mockImplementation<F extends abstract new (...args: any) => any>(method: F, implementation?: (...args: ConstructorParameters<F>) => PartialResolvedType<InstanceType<F>>): MockState<(...args: ConstructorParameters<F>) => PartialResolvedType<InstanceType<F>>>;
182
+ /**
183
+ * Creates a mock implementation of the provided function.
184
+ *
185
+ * @param method - The function to mock
186
+ * @param implementation - Optional custom implementation that returns a partial result
187
+ * @returns The mock state associated with the mocked function
196
188
  *
197
189
  * @remarks
198
- * The `mockImplementation` function creates a new {@link MockState} instance that wraps
199
- * around a provided function, allowing you to monitor calls to that function and optionally
200
- * override its implementation. This is particularly useful for testing components that
201
- * depend on external functions by providing controlled behavior during tests.
190
+ * This overload of the mockImplementation function allows for providing an implementation
191
+ * that returns a partial result object. This is particularly useful when mocking functions
192
+ * that return complex objects where only specific properties are relevant for testing.
202
193
  *
203
- * Responsibilities:
204
- * - Creating a trackable mock function from any original function
205
- * - Supporting custom implementation override capability
206
- * - Preserving the original function's signature and return type
207
- * - Enabling all mock functionality like call tracking and verification
208
- * - Maintaining type safety between the original and mocked functions
194
+ * The implementation preserves the 'this' context from the original function, allowing
195
+ * for proper method mocking on objects.
209
196
  *
210
197
  * @example
211
198
  * ```ts
212
- * // Mock a function with default implementation
213
- * const fetchData = async () => ({ id: 1, name: 'Test' });
214
- * const mockedFetch = xJet.mock(fetchData);
199
+ * interface User {
200
+ * id: number;
201
+ * name: string;
202
+ * email: string;
203
+ * }
215
204
  *
216
- * // Mock with custom implementation
217
- * const mockedFetchCustom = xJet.mock(fetchData, async () => {
218
- * return { id: 2, name: 'Custom Test' };
219
- * });
205
+ * function getUser(id: number): User {
206
+ * // real implementation
207
+ * return { id, name: 'Real User', email: 'user@example.com' };
208
+ * }
220
209
  *
221
- * test('uses mocked function', async () => {
222
- * const result = await mockedFetchCustom();
223
- * expect(result.name).toBe('Custom Test');
224
- * expect(mockedFetchCustom).toHaveBeenCalled();
225
- * });
210
+ * const mockGetUser = mockImplementation(getUser, (id) => ({ id, name: 'Mock User' }));
211
+ * const user = mockGetUser(123); // { id: 123, name: 'Mock User' }
226
212
  * ```
227
213
  *
228
- * @see MockState
229
- * @see FunctionLikeType
230
- * @see ConstructorLikeType
231
- *
232
- * @since 1.2.0
214
+ * @since 1.2.2
233
215
  */
234
- declare function mockImplementation<Method, Args extends Array<unknown> = [], Context = unknown>(method: FunctionLikeType<Method, Args, Context> | ConstructorLikeType<Method, Args>, implementation?: FunctionLikeType<Method, Args, Context>): MockState<Method, Args, Context>;
216
+ declare function mockImplementation<F extends FunctionType>(method: F, implementation?: (...args: Parameters<F>) => PartialResolvedType<ReturnType<F>>): MockState<(this: ThisParameterType<F>, ...args: Parameters<F>) => PartialResolvedType<ReturnType<F>>>;
235
217
  /**
236
218
  * Creates a mock for an element with an optional custom implementation.
237
219
  *
@@ -279,7 +261,7 @@ declare function mockImplementation<Method, Args extends Array<unknown> = [], Co
279
261
  *
280
262
  * @since 1.2.0
281
263
  */
282
- declare function mockImplementation<Element = unknown>(item: Element, implementation?: FunctionLikeType<Element>): MockState<Element>;
264
+ declare function mockImplementation<Element = unknown>(item: Element, implementation?: () => Element): MockState<() => Element>;
283
265
 
284
266
  /**
285
267
  * Import will remove at compile time
@@ -289,9 +271,7 @@ declare function mockImplementation<Element = unknown>(item: Element, implementa
289
271
  * and argument list. This interface extends `MockState` to facilitate tracking
290
272
  * and testing of function behaviors and states.
291
273
  *
292
- * @template ReturnType - Specifies the return type of the function. Defaults to `unknown`.
293
- * @template Context - Defines the function's "this" context type. Defaults to `unknown`.
294
- * @template Args - Sets the argument type(s) for the function, represented as an array. Defaults to `unknown[]`.
274
+ * @template F - The function / class type being mocked
295
275
  *
296
276
  * @remarks
297
277
  * This interface is useful for creating test doubles or mock implementations that simulate
@@ -302,32 +282,83 @@ declare function mockImplementation<Element = unknown>(item: Element, implementa
302
282
  *
303
283
  * @since 1.0.0
304
284
  */
305
- interface FnMockInterface<ReturnType = unknown, Args extends Array<unknown> = any, Context = any> extends MockState<ReturnType, Args, Context> {
306
- new (...args: Args): ReturnType;
307
- (this: Context, ...args: Args): ReturnType;
285
+ interface MockableFunctionInterface<F extends FunctionType> extends MockState<F> {
286
+ /**
287
+ * Constructor signature when the mocked item is used with 'new'
288
+ */
289
+ new (...args: Parameters<F>): ReturnType<F>;
290
+ /**
291
+ * Function call signature preserving 'this' context and parameters
292
+ */
293
+ (this: ThisParameterType<F>, ...args: Parameters<F>): ReturnType<F>;
308
294
  }
295
+ /**
296
+ * Makes properties of a type or its resolved promise value optional.
297
+ *
298
+ * @template T - The type to transform
299
+ *
300
+ * @remarks
301
+ * If T is a Promise-like type, this utility unwraps it and makes the resolved value's
302
+ * properties optional. Otherwise, it directly makes T's properties optional.
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * // Makes properties of User optional
307
+ * type MaybeUser = PartialResolvedType<User>;
308
+ *
309
+ * // Makes properties of resolved User optional
310
+ * type MaybeAsyncUser = PartialResolvedType<Promise<User>>;
311
+ * ```
312
+ *
313
+ * @since 1.2.2
314
+ */
315
+ type PartialResolvedType<T> = T extends PromiseLike<infer U> ? Promise<Partial<U>> : Partial<T>;
309
316
 
310
317
  /**
311
318
  * Import will remove at compile time
312
319
  */
313
320
  /**
314
- * A class representing the mock state for tracking and managing the behavior of mocked functions or classes.
321
+ * A powerful mock state manager for simulating functions and classes in tests.
315
322
  *
316
- * @template ReturnType - The type of value returned by the mock function.
317
- * @template Context - The type representing the context (`this` value) used in the mock function.
318
- * @template Args - The types of arguments for the mocked function.
323
+ * @template F - The function signature being mocked, defaults to any function
319
324
  *
320
325
  * @remarks
321
- * This class provides mechanisms to customize and manage the behavior of mocked functions or constructors.
322
- * It tracks invocation details, allows for behavior customization, and enables resetting or restoring the mock to its original state.
326
+ * MockState provides a complete mocking solution. It tracks
327
+ * all invocations, including arguments, return values, and contexts, while also allowing
328
+ * customization of behavior through various methods like `mockImplementation` and
329
+ * `mockReturnValue`.
330
+ *
331
+ * Key features:
332
+ * - Tracks call arguments, return values, and execution contexts
333
+ * - Supports one-time implementations and return values
334
+ * - Manages Promise resolutions and rejections
335
+ * - Provides methods for resetting or restoring mock state
336
+ * - Preserves the interface of the original function
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * // Create a basic mock
341
+ * const mockFn = new MockState();
323
342
  *
324
- * @since v1.0.0
343
+ * // Configure return values
344
+ * mockFn.mockReturnValue('default');
345
+ * mockFn.mockReturnValueOnce('first call');
346
+ *
347
+ * // Use the mock
348
+ * console.log(mockFn()); // 'first call'
349
+ * console.log(mockFn()); // 'default'
350
+ *
351
+ * // Inspect calls
352
+ * console.log(mockFn.mock.calls); // [[], []]
353
+ * ```
354
+ *
355
+ * @since 1.0.0
325
356
  */
326
- export declare class MockState<ReturnType = unknown, Args extends Array<unknown> = unknown[], Context = unknown> extends Function {
357
+ export declare class MockState<F extends FunctionType = FunctionType> extends Function {
327
358
  /**
328
- * List of all mocks that created
359
+ * List of all mocks that created as WeakRef
329
360
  */
330
- static mocks: Array<MockState>;
361
+ static mocks: Set<WeakRef<MockState>>;
331
362
  /**
332
363
  * The `name` property represents the name of the mock function.
333
364
  */
@@ -337,555 +368,674 @@ export declare class MockState<ReturnType = unknown, Args extends Array<unknown>
337
368
  */
338
369
  readonly xJetMock: boolean;
339
370
  /**
340
- * The `state` property holds the detailed state of the mock invocations.
341
- * It tracks information such as the arguments passed, the results returned, the context (`this` value) used,
342
- * the instances created, and the order of invocations.
343
- * This data is automatically updated after each call to the mock.
371
+ * Holds the current state of the mock, including all invocation records.
344
372
  *
345
- * @template ReturnType - The type of value returned by the mock function.
346
- * @template Context - The type representing the context (`this` value) used in the mock function.
347
- * @template Args - The types of arguments for the mocked function.
373
+ * @remarks
374
+ * This property tracks the complete history of the mock's usage, storing
375
+ * information like call arguments, return values, execution contexts,
376
+ * instances, and the order of invocations.
348
377
  *
349
- * @see MocksStateInterface
378
+ * It's initialized with empty arrays for tracking and gets updated with
379
+ * each invocation. This state is what powers the inspection capabilities
380
+ * accessible via the public `mock` getter.
350
381
  *
351
- * @since v1.0.0
382
+ * @since 1.0.0
352
383
  */
353
384
  private state;
354
385
  /**
355
- * A private function that restores the mock's original implementation.
386
+ * Stores one-time implementations to be used on successive invocations.
356
387
  *
357
388
  * @remarks
358
- * The `restore` function is responsible for resetting the mock to its initial state.
359
- * It works in conjunction with methods like `mockReset` and `mockRestore` to ensure
360
- * proper restoration of the mock's behavior.
389
+ * This queue contains functions that will be consumed in FIFO order
390
+ * (first-in, first-out) when the mock is called. Each implementation
391
+ * is used exactly once and then removed from the queue.
361
392
  *
362
- * Responsibilities:
363
- * - Returning the original implementation when restoring the mock
364
- * - Ensuring consistent reset behavior across mock operations
365
- * - Supporting the {@link mockRestore} method's functionality
366
- * - Maintaining mock state integrity during restoration
393
+ * When adding implementations with `mockImplementationOnce()` or similar
394
+ * methods, they are pushed to this queue. On invocation, the mock will
395
+ * check this queue first, using and removing the oldest implementation
396
+ * if available, or falling back to the default implementation.
367
397
  *
368
- * @see MockState.mockRestore
369
- * @see MockState.originalImplementation
370
- *
371
- * @since 1.2.0
398
+ * @since 1.0.0
372
399
  */
373
- private readonly restore?;
400
+ private queuedImplementations;
374
401
  /**
375
- * A private array that stores the implementations queued to be executed
376
- * for future invocations of the mock.
377
- * Each function in this array is invoked in sequence when the mock function is called,
378
- * with the first queued implementation being used on the first call, the second on the second call, and so on.
402
+ * The current default implementation for this mock.
379
403
  *
380
- * This property is used in conjunction with methods like `mockImplementationOnce`
381
- * to specify different behaviors for consecutive calls to the mock.
404
+ * @remarks
405
+ * This property holds the function that will be executed when the mock is called,
406
+ * unless overridden by a queued one-time implementation. It can be set using
407
+ * the `mockImplementation()` method and retrieved with `getMockImplementation()`.
382
408
  *
383
- * @since v1.0.0
384
- */
385
- private queuedImplementations;
386
- /**
387
- * A private property that holds the current implementation of the mock function.
388
- * This function is executed whenever the mock is invoked and can be changed
389
- * using methods like `mockImplementation` or `mockImplementationOnce`.
409
+ * If not explicitly set, it defaults to `undefined`, meaning the mock will
410
+ * return `undefined` when called (after any queued implementations are used).
390
411
  *
391
- * The `implementation` allows for customizing the behavior of the mock,
392
- * such as returning specific values, throwing errors, or performing actions.
412
+ * This implementation determines the behavior of the mock for all calls that
413
+ * don't have a specific one-time implementation in the queue.
393
414
  *
394
- * @since v1.0.0
415
+ * @since 1.0.0
395
416
  */
396
417
  private implementation;
397
418
  /**
398
- * A private property that holds the original implementation of the mock function.
399
- * This is the initial function passed to the constructor that defines the mock's default behavior
400
- * before any customization.
401
- *
402
- * @template ReturnType - The type of value returned by the original function.
403
- * @template Args - The types of arguments for the original function.
404
- * @template Context - The type representing the context (`this` value) used in the original function.
419
+ * Preserves the original implementation provided when creating the mock.
405
420
  *
406
421
  * @remarks
407
- * This property stores the initial implementation provided when creating the mock.
408
- * If no implementation is provided during construction, it defaults to a function
409
- * that returns `undefined` cast to the appropriate return type.
410
- * Unlike `implementation` which can be modified, this property maintains a reference
411
- * to the original function for scenarios where the original behavior needs to be preserved
412
- * or restored.
422
+ * This property stores the initial function passed to the constructor, allowing
423
+ * the mock to be restored to its original behavior later using `mockRestore()`.
424
+ *
425
+ * If no implementation was provided in the constructor, this will contain a
426
+ * function that returns `undefined` when called.
413
427
  *
414
- * @see FunctionLikeType
415
- * @see MockState.original
428
+ * The original implementation is immutable and serves as a reference point
429
+ * for resetting the mock to its initial state.
416
430
  *
417
431
  * @since 1.0.0
418
432
  */
419
433
  private readonly originalImplementation;
420
434
  /**
421
- * Constructs a mock object that allows custom implementation, restore capability,
422
- * and optional naming functionality. This mock is proxied to handle function invocation
423
- * and class instantiation.
435
+ * Optional cleanup function to be called when the mock is restored.
436
+ *
437
+ * @remarks
438
+ * If provided, this function will be executed when `mockRestore()` is called,
439
+ * allowing for custom cleanup operations. This is particularly useful when
440
+ * creating mocks that replace methods or properties on existing objects.
424
441
  *
425
- * @template ReturnType - The type of the value returned by the mock function.
426
- * @template Context - The type of the context (`this`) for the mock function.
427
- * @template Args - The type of arguments accepted by the mock function.
442
+ * The restore function should handle any necessary teardown, such as
443
+ * restoring original object properties, removing event listeners, or
444
+ * closing connections that were established during mock creation.
445
+ *
446
+ * @since 1.0.0
447
+ */
448
+ private readonly restore?;
449
+ /**
450
+ * Creates a new instance of a mock function.
428
451
  *
429
- * @param implementation - Optional implementation for the mock function.
430
- * @param restore - Optional function to restore the mock to its initial state. Defaults to resetting to the provided implementation.
431
- * @param name - Optional name for the mock instance. Default to a predefined mock name if not provided.
452
+ * @template F - The function type being mocked. This generic type parameter allows
453
+ * the mock to properly type-check parameters and return values to match
454
+ * the function signature being mocked.
432
455
  *
433
- * @returns A proxied mock object capable of behaving as a callable function or a constructible class.
456
+ * @param implementation - The initial function implementation to use. If not provided,
457
+ * the mock will return `undefined` when called.
458
+ * @param restore - Optional cleanup function that will be called when `mockRestore()` is invoked.
459
+ * Useful for restoring original behavior when mocking existing object methods.
460
+ * @param name - Optional name for the mock function, used in error messages and test output.
461
+ * Defaults to "xJet.fn()" if not provided.
434
462
  *
435
463
  * @remarks
436
- * The mock object can work as both a function and a class, using JavaScript's Proxy API. The restore functionality
437
- * allows resetting to the original state or implementation. If no implementation is provided, the mock remains uninitialized
438
- * but still functional.
464
+ * The constructor initializes the mock's state, implementation, and metadata.
465
+ * It returns a Proxy that allows the mock to be both a function and an object with properties.
439
466
  *
440
- * @see FunctionLikeType
441
- * @see VoidFunctionType
467
+ * The Proxy intercepts:
468
+ * - Function calls (via `apply`)
469
+ * - Property access (via `get`)
470
+ * - Constructor calls with `new` (via `construct`)
471
+ *
472
+ * This enables the mock to track calls, return configured values, and provide
473
+ * helper methods for assertions and configuration.
474
+ *
475
+ * @see ReturnType
476
+ * @see ImplementationType
442
477
  *
443
478
  * @since 1.0.0
444
479
  */
445
- constructor(implementation?: FunctionLikeType<ReturnType, Args, Context>, restore?: () => FunctionLikeType<ReturnType, Args, Context> | void, name?: string);
446
- /**
447
- * todo remove it
448
- * only for jest expect will support this mock
449
- */
450
- getMockName(): string;
480
+ constructor(implementation?: F, restore?: () => F | void, name?: string);
451
481
  /**
452
- * Retrieves the current state of the mock function.
482
+ * Gets a readonly snapshot of the current mocks state.
453
483
  *
454
- * @remarks
455
- * The `mock` getter provides read-only access to the complete state tracking information
456
- * for the mock function. This includes all recorded invocations, return values, contexts,
457
- * and other mock-related tracking data.
484
+ * @template F - The function type being mocked.
458
485
  *
459
- * Responsibilities:
460
- * - Providing access to recorded function calls via {@link MocksStateInterface.calls}
461
- * - Tracking invocation results through {@link MocksStateInterface.results}
462
- * - Maintaining context information in {@link MocksStateInterface.contexts}
463
- * - Recording instance creation in {@link MocksStateInterface.instances}
464
- * - Preserving invocation order via {@link MocksStateInterface.invocationCallOrder}
486
+ * @returns A frozen (immutable) copy of the mock state {@link MocksStateInterface}, containing information
487
+ * about calls, return values, and other tracking data.
465
488
  *
466
- * @returns A read-only view of the mock state tracking object.
489
+ * @remarks
490
+ * This property provides safe access to the mock's internal state for assertions and
491
+ * debugging purposes. The returned object is a deep copy with all properties frozen
492
+ * to prevent accidental modification of the mock's internal state.
467
493
  *
468
494
  * @see MocksStateInterface
495
+ *
469
496
  * @since 1.0.0
470
497
  */
471
- get mock(): Readonly<MocksStateInterface<ReturnType, Args, Context>>;
498
+ get mock(): Readonly<MocksStateInterface<F>>;
472
499
  /**
473
- * Returns the original implementation of the function that was instrumented
500
+ * Gets the original function implementation.
501
+ *
502
+ * @template F - The function type being mocked.
474
503
  *
475
- * @returns The original function implementation that was wrapped or modified
504
+ * @returns The original function implementation that was provided when creating the mock
505
+ * or a default implementation that returns undefined if none was provided.
476
506
  *
477
507
  * @remarks
478
- * This getter provides access to the unmodified function that was originally passed
479
- * to the instrumentation system. Useful for debugging, testing, or when you need
480
- * to bypass the instrumented behavior temporarily.
508
+ * This property allows access to the original implementation that was stored
509
+ * when the mock was created. It's useful when you need to temporarily access
510
+ * or call the original behavior within test cases.
481
511
  *
482
512
  * @example
483
513
  * ```ts
484
- * const mockFn = jest.fn(x => x * 2);
485
- * // Later in test
486
- * const originalImplementation = mockFn.original;
487
- * expect(originalImplementation(5)).toBe(10);
488
- * ```
514
+ * // Create a mock with an original implementation
515
+ * const originalFn = (x: number) => x * 2;
516
+ * const mockFn = xJet.fn(originalFn);
489
517
  *
490
- * @see FunctionLikeType
518
+ * // Override the implementation for some tests
519
+ * mockFn.mockImplementation((x: number) => x * 3);
520
+ *
521
+ * // Call the original implementation directly when needed
522
+ * const result = mockFn.original(5); // Returns 10, not 15
523
+ * ```
491
524
  *
492
525
  * @since 1.0.0
493
526
  */
494
- get original(): FunctionLikeType<ReturnType, Args, Context>;
527
+ get original(): F;
495
528
  /**
496
- * Clears the `mock.calls`, `mock.results`, `mock.contexts`, `mock.instances`, and `mock.invocationCallOrder` properties.
529
+ * Clears all information stored in the mock's state {@link MocksStateInterface}.
497
530
  *
498
- * @returns The current instance of the mock, allowing for method chaining.
531
+ * @returns The mock instance for method chaining.
499
532
  *
500
533
  * @remarks
501
- * This method resets the state of the mock function, clearing all invocation data and results,
502
- * ensuring that previous mock states do not affect the following tests.
503
- * Equivalent to calling `.mockClear()` on every mocked function.
534
+ * This method resets all stored information such as tracked calls, return values,
535
+ * and other state information. It doesn't reset any custom implementations that
536
+ * were set using mockImplementation or similar methods.
504
537
  *
505
- * @see MockState.initState
538
+ * @example
539
+ * ```ts
540
+ * const mockFn = xJet.fn();
541
+ * mockFn('first call');
542
+ * mockFn('second call');
543
+ *
544
+ * expect(mockFn.mock.calls.length).toBe(2);
545
+ *
546
+ * mockFn.mockClear();
547
+ *
548
+ * // All calls information has been cleared
549
+ * expect(mockFn.mock.calls.length).toBe(0);
550
+ * ```
506
551
  *
507
- * @since v1.0.0
552
+ * @since 1.0.0
508
553
  */
509
554
  mockClear(): this;
510
555
  /**
511
- * Resets the mock function to its initial state.
556
+ * Resets the mock by clearing all state and removing all queued implementations.
512
557
  *
513
- * @returns The current instance of the mock, allowing for method chaining.
558
+ * @returns The mock instance for method chaining.
514
559
  *
515
560
  * @remarks
516
- * The `mockReset` method clears all invocation data and results by calling `mockClear()` and also resets
517
- * the queued implementations,
518
- * removing any previously queued behavior set by methods like `mockImplementationOnce`.
519
- * This ensures that the mock is in a clean state and ready for new invocations or configurations.
561
+ * This method performs a more complete reset than mockClear() {@link mockClear}.
562
+ * It clears all stored information about calls and additionally removes any queued implementations that were
563
+ * set using mockImplementationOnce(). The default implementation will be restored.
564
+ *
565
+ * @example
566
+ * ```ts
567
+ * const mockFn = xJet.fn(() => 'default');
568
+ * mockFn.mockImplementationOnce(() => 'first call');
569
+ * mockFn.mockImplementationOnce(() => 'second call');
570
+ *
571
+ * console.log(mockFn()); // 'first call'
572
+ *
573
+ * mockFn.mockReset();
520
574
  *
521
- * @see MockState.mockClear
575
+ * // All calls have been cleared, and queued implementations removed
576
+ * console.log(mockFn()); // 'default'
577
+ * ```
522
578
  *
523
- * @since v1.0.0
579
+ * @see mockClear
580
+ * @since 1.0.0
524
581
  */
525
582
  mockReset(): this;
526
583
  /**
527
- * Restores the mock function to its original implementation and resets its state.
584
+ * Restores the original implementation of the mocked function.
528
585
  *
529
- * @returns The current instance of the mock, allowing for method chaining.
586
+ * @returns The mock instance for method chaining.
530
587
  *
531
588
  * @remarks
532
- * The `mockRestore` method does two things:
533
- * 1. It restores the mock to its initial implementation, which was set during the mocks creation or
534
- * via the `mockImplementation` method.
535
- * 2. It clears all tracking data, such as calls, results, contexts, instances, and invocation call order
536
- * by calling `mockReset()`, ensuring the mock is fully reset and ready for new invocations.
589
+ * This method performs the most complete reset operation. It first calls mockReset() {@link mockReset}
590
+ * to clear all state and queued implementations, then restores the original implementation
591
+ * provided when the mock was created. If a custom restore function was provided,
592
+ * it will be used instead to determine the implementation to restore.
537
593
  *
538
- * This method is useful for ensuring that the mock is completely restored and cleared, making it behave as it did
539
- * when it was first created or last restored.
594
+ * @example
595
+ * ```ts
596
+ * // Create a mock with an original implementation
597
+ * const originalFn = (x: number) => x * 2;
598
+ * const mockFn = xJet.fn(originalFn);
599
+ *
600
+ * // Override the implementation
601
+ * mockFn.mockImplementation((x: number) => x * 3);
602
+ *
603
+ * console.log(mockFn(5)); // 15
540
604
  *
541
- * @see MockState.restore
542
- * @see MockState.mockReset
605
+ * // Restore the original implementation
606
+ * mockFn.mockRestore();
607
+ *
608
+ * console.log(mockFn(5)); // 10
609
+ * ```
543
610
  *
544
- * @since v1.0.0
611
+ * @see mockClear
612
+ * @see mockReset
613
+ *
614
+ * @since 1.0.0
545
615
  */
546
616
  mockRestore(): this;
547
617
  /**
548
- * Retrieves the mock implementation for a function, if available.
549
- *
550
- * @template ReturnType The type the return value of the function.
551
- * @template Context The type of the `this` context for the function.
552
- * @template Args The type the argument(s) of the function.
618
+ * Returns the current implementation of the mock function.
553
619
  *
554
- * @return A function matching `FunctionLikeType` that represents the mock implementation,
555
- * or `undefined` if no implementation is set.
620
+ * @returns The current mock implementation, or undefined if no implementation exists.
556
621
  *
557
622
  * @remarks
558
- * This method returns the mock implementation associated with the instance.
559
- * If no mock implementation exists, it returns `undefined`.
623
+ * This method returns the current implementation function used by the mock.
624
+ * This could be the default implementation, a custom implementation set via
625
+ * mockImplementation() {@link mockImplementation}, or the original implementation
626
+ * if mockRestore() {@link mockRestore} was called.
627
+ *
628
+ * @example
629
+ * ```ts
630
+ * const mockFn = xJet.fn(() => 'default');
631
+ *
632
+ * // Get the default implementation
633
+ * const impl = mockFn.getMockImplementation();
634
+ * console.log(impl()); // 'default'
635
+ *
636
+ * // Change the implementation
637
+ * mockFn.mockImplementation(() => 'new implementation');
638
+ *
639
+ * // Get the new implementation
640
+ * const newImpl = mockFn.getMockImplementation();
641
+ * console.log(newImpl()); // 'new implementation'
642
+ * ```
560
643
  *
561
644
  * @since 1.0.0
562
645
  */
563
- getMockImplementation(): FunctionLikeType<ReturnType, Args, Context> | undefined;
646
+ getMockImplementation(): ImplementationType<F> | undefined;
564
647
  /**
565
- * Retrieves the next implementation from the queued implementations or defaults to the current implementation.
648
+ * Returns the next implementation to be used when the mock is called.
566
649
  *
567
- * @template ReturnType The return type of the function-like implementation.
568
- * @template Context The context in which the implementation executes.
569
- * @template Args The argument types expected by the implementation.
570
- *
571
- * @return The next implementation from the queue if available, or the current implementation.
572
- * Returns are `undefined` if no implementation is found.
650
+ * @returns The next implementation from the queue, or the default implementation if the queue is empty.
573
651
  *
574
652
  * @remarks
575
- * This method first checks if there are any queued implementations available.
576
- * If a queued implementation exists, it will be removed from the queue and returned.
577
- * If the queue is empty, the primary current implementation is returned.
578
- * Returns are `undefined` if there is no implementation available.
653
+ * This method retrieves and removes the next implementation from the queue of implementations
654
+ * added via mockImplementationOnce() {@link mockImplementationOnce}. If the queue is empty,
655
+ * it returns the default implementation set via mockImplementation() {@link mockImplementation}
656
+ * or the original function.
657
+ *
658
+ * @example
659
+ * ```ts
660
+ * const mockFn = xJet.fn(() => 'default');
661
+ * mockFn.mockImplementationOnce(() => 'first call');
662
+ * mockFn.mockImplementationOnce(() => 'second call');
663
+ *
664
+ * const firstImpl = mockFn.getNextImplementation();
665
+ * console.log(firstImpl()); // 'first call'
666
+ *
667
+ * const secondImpl = mockFn.getNextImplementation();
668
+ * console.log(secondImpl()); // 'second call'
669
+ *
670
+ * const defaultImpl = mockFn.getNextImplementation();
671
+ * console.log(defaultImpl()); // 'default'
672
+ * ```
579
673
  *
580
674
  * @since 1.0.0
581
675
  */
582
- getNextImplementation(): FunctionLikeType<ReturnType, Args, Context> | undefined;
676
+ getNextImplementation(): ImplementationType<F> | undefined;
583
677
  /**
584
- * Replaces the default implementation of a mock function with the provided function.
678
+ * Sets a new implementation for this mock function.
585
679
  *
586
- * @template ReturnType - The type of the value returned by the implementation function.
587
- * @template Context - The context (`this`) expected by the implementation function.
588
- * @template Args - The types of the arguments expected by the implementation function.
680
+ * @param fn - The function to be used as the mock implementation.
681
+ * @returns The mock instance for method chaining.
589
682
  *
590
- * @param fn - The function to be used as the mock implementation. It defines
591
- * the behavior of the mock when called.
683
+ * @remarks
684
+ * This method sets a persistent implementation that will be used whenever the mock function is called,
685
+ * unless there are queued implementations from mockImplementationOnce() {@link mockImplementationOnce}.
686
+ * The implementation remains until it is replaced by another call to mockImplementation() or restored
687
+ * via mockRestore() {@link mockRestore}.
592
688
  *
593
- * @return Returns the instance of the current object for method chaining.
689
+ * @example
690
+ * ```ts
691
+ * const mockFn = xJet.fn();
594
692
  *
595
- * @remarks
596
- * This method is useful when you need to mock the behavior of a function
597
- * dynamically during tests or in controlled scenarios.
693
+ * mockFn.mockImplementation((x: number) => x * 2);
694
+ *
695
+ * console.log(mockFn(5)); // 10
696
+ * console.log(mockFn(10)); // 20
697
+ *
698
+ * // Change the implementation
699
+ * mockFn.mockImplementation((x: number) => x * 3);
700
+ *
701
+ * console.log(mockFn(5)); // 15
702
+ * ```
703
+ *
704
+ * @see mockRestore
705
+ * @see mockImplementationOnce
598
706
  *
599
707
  * @since 1.0.0
600
708
  */
601
- mockImplementation(fn: FunctionLikeType<ReturnType, Args, Context>): this;
709
+ mockImplementation(fn: ImplementationType<F>): this;
602
710
  /**
603
- * Sets a mock implementation that will be used once for the next call to the mocked function.
604
- *
605
- * @template ReturnType The type of the value that the mock function will return.
606
- * @template Context The type of the `this` context for the mock function.
607
- * @template Args The type of arguments that the mock function will receive.
711
+ * Adds a one-time implementation for this mock function.
608
712
  *
609
- * @param fn - The function to be used as the mock implementation for the next call.
610
- * @returns The current instance, allowing for chaining of mock configurations.
713
+ * @param fn - The function to be used as the mock implementation for a single call.
714
+ * @returns The mock instance for method chaining.
611
715
  *
612
716
  * @remarks
613
- * The provided mock implementation will only be executed once. Further calls will fall back
614
- * to a different implementation, if provided, or the default behavior of the mock function.
717
+ * This method queues an implementation that will be used for a single call to the mock function.
718
+ * After being used once, it will be removed from the queue. Multiple implementations can be queued,
719
+ * and they will be used in the order they were added. Once all queued implementations are used,
720
+ * the mock will revert to using the implementation set by mockImplementation() {@link mockImplementation}.
615
721
  *
616
722
  * @example
617
723
  * ```ts
618
- * const mockFn = new MockState();
724
+ * const mockFn = xJet.fn(() => 'default');
619
725
  *
620
- * // Set default implementation
621
- * mockFn.mockImplementation(() => 'default');
622
- *
623
- * // Set one-time behavior for the next call
624
- * mockFn.mockImplementationOnce(() => 'first call');
726
+ * mockFn.mockImplementationOnce(() => 'first call')
727
+ * .mockImplementationOnce(() => 'second call');
625
728
  *
626
- * console.log(mockFn()); // Output: 'first call' (from mockImplementationOnce)
627
- * console.log(mockFn()); // Output: 'default' (from mockImplementation)
729
+ * console.log(mockFn()); // 'first call'
730
+ * console.log(mockFn()); // 'second call'
731
+ * console.log(mockFn()); // 'default'
628
732
  * ```
629
733
  *
630
- * @see FunctionLikeType
734
+ * @see mockReset
735
+ * @see mockImplementation
631
736
  *
632
737
  * @since 1.0.0
633
738
  */
634
- mockImplementationOnce(fn: FunctionLikeType<ReturnType, Args, Context>): this;
739
+ mockImplementationOnce(fn: ImplementationType<F>): this;
635
740
  /**
636
- * Sets a mock implementation to always return a specified value when invoked.
741
+ * Sets a fixed return value for this mock function.
637
742
  *
638
- * @template ReturnType The type of the value returned by the mock implementation.
639
- *
640
- * @param value - The value to always return when the mock function is called.
641
- * @return The current instance for chaining.
743
+ * @param value - The value to be returned when the mock function is called.
744
+ * @returns The mock instance for method chaining.
642
745
  *
643
746
  * @remarks
644
- * This method overrides any previous mock implementation configured for the function.
747
+ * This method is a convenience wrapper around mockImplementation() {@link mockImplementation}
748
+ * that creates an implementation which always returns the same value. It replaces any existing
749
+ * implementation with a function that simply returns the specified value.
645
750
  *
646
751
  * @example
647
752
  * ```ts
648
- * const mockFn = new MockState();
753
+ * const mockFn = xJet.fn();
754
+ *
755
+ * mockFn.mockReturnValue(42);
649
756
  *
650
- * // Set mock to return 'Hello World' on each call
651
- * mockFn.mockReturnValue('Hello World');
757
+ * console.log(mockFn()); // 42
758
+ * console.log(mockFn('anything')); // 42
759
+ * console.log(mockFn({}, [])); // 42
652
760
  *
653
- * console.log(mockFn()); // Output: 'Hello World'
654
- * console.log(mockFn()); // Output: 'Hello World'
761
+ * // Can be changed
762
+ * mockFn.mockReturnValue('new value');
763
+ * console.log(mockFn()); // 'new value'
655
764
  * ```
656
765
  *
766
+ * @see mockImplementation
767
+ * @see mockReturnValueOnce
768
+ *
657
769
  * @since 1.0.0
658
770
  */
659
- mockReturnValue(value: ReturnType): this;
771
+ mockReturnValue(value: ReturnType<F>): this;
660
772
  /**
661
- * Sets up a mock function to always resolve a promise with the specified value when called.
773
+ * Adds a one-time fixed return value for this mock function.
662
774
  *
663
- * @template ResolvedValueType - The type of the value to be resolved by the promise.
664
- * @template ReturnType - The return type of the function, which should include a Promise of the specified resolved value type.
665
- *
666
- * @param value - The value to be returned as the resolved value of the promise.
667
- * @returns The mock function instance, enabling method chaining.
775
+ * @param value - The value to be returned for a single call to the mock function.
776
+ * @returns The mock instance for method chaining.
668
777
  *
669
778
  * @remarks
670
- * This method is particularly useful for mocking asynchronous functions that return promises.
671
- * It ensures that the mock function resolves with the provided value every time it is called.
779
+ * This method is a convenience wrapper around mockImplementationOnce() {@link mockImplementationOnce}
780
+ * that creates a one-time implementation which returns the specified value. Multiple return values
781
+ * can be queued, and they will be used in the order they were added. After all queued values are
782
+ * consumed, the mock will revert to its default implementation.
672
783
  *
673
784
  * @example
674
785
  * ```ts
675
- * const mockFn = new MockState<Promise<string>>();
786
+ * const mockFn = xJet.fn(() => 'default');
676
787
  *
677
- * // Set mock to return a resolved promise with the value 'Success'
678
- * mockFn.mockResolvedValue('Success');
788
+ * mockFn.mockReturnValueOnce(42)
789
+ * .mockReturnValueOnce('string value')
790
+ * .mockReturnValueOnce({ object: true });
679
791
  *
680
- * mockFn().then((result: string) => {
681
- * console.log(result); // Output: 'Success'
682
- * });
792
+ * console.log(mockFn()); // 42
793
+ * console.log(mockFn()); // 'string value'
794
+ * console.log(mockFn()); // { object: true }
795
+ * console.log(mockFn()); // 'default'
683
796
  * ```
684
797
  *
798
+ * @see mockReturnValue
799
+ * @see mockImplementationOnce
800
+ *
685
801
  * @since 1.0.0
686
802
  */
687
- mockResolvedValue(value: ResolvedValueType<ReturnType>): this;
803
+ mockReturnValueOnce(value: ReturnType<F>): this;
688
804
  /**
689
- * Sets a mock implementation for a single call that resolves to the specified value.
805
+ * Sets a resolved Promise return value for this mock function.
690
806
  *
691
- * @template ReturnType The type of the resolved value.
692
- * @template ResolvedValueType The type of the input value to be resolved.
693
- *
694
- * @param value - The value that the promise should resolve with when the mock is called once.
695
- * @return The current mock object instance, enabling method chaining.
807
+ * @param value - The value that the Promise will resolve to.
808
+ * @returns The mock instance for method chaining.
696
809
  *
697
810
  * @remarks
698
- * This method is useful for defining custom behavior for a specific invocation of a mocked function,
699
- * returning a resolved promise with the provided value.
811
+ * This method is a convenience wrapper that creates an implementation which returns a
812
+ * Promise that resolves to the specified value. It's particularly useful for testing
813
+ * async functions that should return resolved Promises.
700
814
  *
701
815
  * @example
702
816
  * ```ts
703
- * const mockFn = new MockState(async () => {
704
- * return 'end';
705
- * });
817
+ * const mockFn = xJet.fn();
706
818
  *
707
- * // Set mock to return a resolved promise with the value 'Success'
708
- * mockFn.mockResolvedValueOnce('Success');
819
+ * mockFn.mockResolvedValue('resolved value');
709
820
  *
710
- * mockFn().then((result: string) => {
711
- * console.log(result); // Output: 'Success'
821
+ * // The mock now returns a Promise that resolves to 'resolved value'
822
+ * mockFn().then(result => {
823
+ * console.log(result); // 'resolved value'
712
824
  * });
713
825
  *
714
- * mockFn().then((result: string) => {
715
- * console.log(result); // Output: 'end'
716
- * });
826
+ * // Can also be used with async/await
827
+ * const result = await mockFn();
828
+ * console.log(result); // 'resolved value'
717
829
  * ```
718
830
  *
831
+ * @see mockRejectedValue
832
+ * @see mockImplementation
833
+ * @see mockResolvedValueOnce
834
+ *
719
835
  * @since 1.0.0
720
836
  */
721
- mockResolvedValueOnce(value: ResolvedValueType<ReturnType>): this;
837
+ mockResolvedValue(value: ResolvedValueType<ReturnType<F>>): this;
722
838
  /**
723
- * Sets the return value of the mock function for a single call.
724
- *
725
- * @template ReturnType The type of the value to be returned.
839
+ * Adds a one-time resolved Promise return value for this mock function.
726
840
  *
727
- * @param value - The value to be returned by the mock function for the next call.
728
- * @return The mock function instance, allowing for method chaining.
841
+ * @param value - The value that the Promise will resolve to for a single call.
842
+ * @returns The mock instance for method chaining.
729
843
  *
730
844
  * @remarks
731
- * This method only affects the return value for the next call to the mock function.
732
- * All further calls will use the usual mock implementation or other specified behaviors.
845
+ * This method is a convenience wrapper that creates a one-time implementation which returns
846
+ * a Promise that resolves to the specified value. Multiple resolved values can be queued and
847
+ * will be used in the order they were added. After all queued values are consumed, the mock
848
+ * will revert to its default implementation.
733
849
  *
734
850
  * @example
735
851
  * ```ts
736
- * const mockFn = new MockState();
852
+ * const mockFn = xJet.fn(() => Promise.resolve('default'));
737
853
  *
738
- * // Set default return value
739
- * mockFn.mockReturnValue('Default Value');
854
+ * mockFn.mockResolvedValueOnce('first call')
855
+ * .mockResolvedValueOnce('second call')
856
+ * .mockResolvedValueOnce('third call');
740
857
  *
741
- * // Set a one-time return value for the next call
742
- * mockFn.mockReturnValueOnce('First Call');
743
- * mockFn.mockReturnValueOnce('Second Call');
744
- *
745
- * console.log(mockFn()); // Output: 'First Call' (from mockReturnValueOnce)
746
- * console.log(mockFn()); // Output: 'Second Call' (from mockReturnValueOnce)
747
- * console.log(mockFn()); // Output: 'Default Value' (from mockReturnValue)
858
+ * // Each call returns a different Promise
859
+ * await expect(mockFn()).resolves.toEqual('first call');
860
+ * await expect(mockFn()).resolves.toEqual('second call');
861
+ * await expect(mockFn()).resolves.toEqual('third call');
862
+ * await expect(mockFn()).resolves.toEqual('default');
748
863
  * ```
749
864
  *
865
+ * @see mockResolvedValue
866
+ * @see mockRejectedValueOnce
867
+ * @see mockImplementationOnce
868
+ *
750
869
  * @since 1.0.0
751
870
  */
752
- mockReturnValueOnce(value: ReturnType): this;
871
+ mockResolvedValueOnce(value: ResolvedValueType<ReturnType<F>>): this;
753
872
  /**
754
- * Mocks the method to always return a rejected Promise with the specified value.
755
- *
756
- * @template ReturnType - The expected type of the return value for the mocked method.
757
- * @template RejectedValueType - The type of the value used to reject the Promise.
873
+ * Sets a rejected Promise return value for this mock function.
758
874
  *
759
- * @param value - The value with which the mocked Promise will be rejected.
760
- *
761
- * @return The current instance of the mock for chaining purposes.
875
+ * @param value - The error that the Promise will reject with.
876
+ * @returns The mock instance for method chaining.
762
877
  *
763
878
  * @remarks
764
- * This method is useful for testing scenarios where the function being mocked
765
- * is expected to reject with a specific value.
879
+ * This method is a convenience wrapper that creates an implementation which returns a
880
+ * Promise that rejects with the specified value. It's particularly useful for testing
881
+ * error handling in async functions.
766
882
  *
767
883
  * @example
768
884
  * ```ts
769
- * const mockFn = new MockState<Promise<string>>();
885
+ * const mockFn = xJet.fn();
770
886
  *
771
- * // Set mock to return a rejected promise with the value 'Error'
772
- * mockFn.mockRejectedValue('Error');
887
+ * mockFn.mockRejectedValue(new Error('Something went wrong'));
773
888
  *
889
+ * // The mock now returns a Promise that rejects with the error
774
890
  * mockFn().catch(error => {
775
- * console.log(error); // Output: 'Error'
891
+ * console.error(error.message); // 'Something went wrong'
776
892
  * });
893
+ *
894
+ * // Can also be used with async/await and try/catch
895
+ * try {
896
+ * await mockFn();
897
+ * } catch (error) {
898
+ * console.error(error.message); // 'Something went wrong'
899
+ * }
777
900
  * ```
778
901
  *
902
+ * @see mockResolvedValue
903
+ * @see mockImplementation
904
+ * @see mockRejectedValueOnce
905
+ *
779
906
  * @since 1.0.0
780
907
  */
781
- mockRejectedValue(value: RejectedValueType<ReturnType>): this;
908
+ mockRejectedValue(value: RejectedValueType<ReturnType<F>>): this;
782
909
  /**
783
- * Adds a one-time rejection with the provided value to the mock function.
784
- *
785
- * @template ReturnType - The type of the value the mock function would return.
910
+ * Adds a one-time rejected Promise return value for this mock function.
786
911
  *
787
- * @param value - The value to reject the promise with in the mock function.
788
- * @return The current instance of the mock function, allowing for method chaining.
912
+ * @param value - The error that the Promise will reject with for a single call.
913
+ * @returns The mock instance for method chaining.
789
914
  *
790
915
  * @remarks
791
- * This method configures a mock function to return a rejected promise with the
792
- * specified value the next time it is called. After the rejection occurs, the
793
- * mock function's behavior will revert to the next defined mock behavior, or
794
- * to the default behavior if no behaviors are defined.
916
+ * This method is a convenience wrapper that creates a one-time implementation which returns
917
+ * a Promise that rejects with the specified value. Multiple rejected values can be queued and
918
+ * will be used in the order they were added. After all queued values are consumed, the mock
919
+ * will revert to its default implementation.
795
920
  *
796
921
  * @example
797
922
  * ```ts
798
- * const mockFn = new MockState<Promise<string>>();
923
+ * const mockFn = xJet.fn(() => Promise.resolve('success'));
799
924
  *
800
- * // Set default rejected value
801
- * mockFn.mockRejectedValue('Default Error');
925
+ * mockFn.mockRejectedValueOnce(new Error('first error'))
926
+ * .mockRejectedValueOnce(new Error('second error'));
802
927
  *
803
- * // Set a one-time rejected value for the next call
804
- * mockFn.mockRejectedValueOnce('First Call Error');
928
+ * // First call rejects with 'first error'
929
+ * await expect(mockFn()).rejects.toThrow('first error');
805
930
  *
806
- * mockFn().catch(error => {
807
- * console.log(error); // Output: 'First Call Error' (from mockRejectedValueOnce)
808
- * });
931
+ * // Second call rejects with 'second error'
932
+ * await expect(mockFn()).rejects.toThrow('second error');
809
933
  *
810
- * mockFn().catch(error => {
811
- * console.log(error); // Output: 'Default Error' (from mockRejectedValue)
812
- * });
934
+ * // Third call uses the default implementation and resolves
935
+ * await expect(mockFn()).resolves.toEqual('success');
813
936
  * ```
814
937
  *
938
+ * @see mockRejectedValue
939
+ * @see mockResolvedValueOnce
940
+ * @see mockImplementationOnce
941
+ *
815
942
  * @since 1.0.0
816
943
  */
817
- mockRejectedValueOnce(value: RejectedValueType<ReturnType>): this;
944
+ mockRejectedValueOnce(value: RejectedValueType<ReturnType<F>>): this;
818
945
  /**
819
- * Initializes and returns the state object for mock function tracking.
946
+ * Initializes the internal state object for the mock function.
820
947
  *
821
- * @return An object containing the initialized mock function state.
948
+ * @returns A new mock state object with default empty values.
822
949
  *
823
950
  * @remarks
824
- * The state object contains the structure necessary to keep track of
825
- * calls, results, contexts, instances, and invocation orders of the function.
951
+ * This private method creates and returns a fresh state object used to track
952
+ * mock function invocations. The state includes:
953
+ * - calls: Arguments passed to the mock function
954
+ * - results: Return values or errors from each call
955
+ * - lastCall: Arguments from the most recent call
956
+ * - contexts: 'this' context values for each call
957
+ * - instances: Objects created when the mock is used as a constructor
958
+ * - invocationCallOrder: Tracking the sequence of calls across multiple mocks
826
959
  *
827
- * @see MocksStateInterface
960
+ * This method is used internally when creating a new mock or when resetting
961
+ * an existing mocks state.
828
962
  *
829
- * @since v1.0.0
963
+ * @since 1.0.0
830
964
  */
831
965
  private initState;
832
966
  /**
833
- * Invokes the next implementation of a mock function with the provided context and arguments.
834
- *
835
- * @template Context The type of `this` context in which the function is invoked.
836
- * @template Args The type of the arguments passed to the function.
837
- * @template ReturnType The type of the return value, of the function being invoked.
967
+ * Invokes the mock function with the provided arguments and context.
838
968
  *
839
- * @param thisArg - The context (`this`) in which the function is executed.
840
- * @param args - The arguments to be passed to the function.
841
- *
842
- * @returns The result of the function invocation, which is either the return value, the thrown error, or undefined.
969
+ * @param thisArg - The 'this' context for the function call
970
+ * @param args - The arguments to pass to the function
971
+ * @returns The result of the mock implementation or undefined
843
972
  *
844
973
  * @remarks
845
- * This method simulates the function call for a mocked implementation. It tracks all invocations,
846
- * including the call order, the provided arguments, and the context. It handles binding, default
847
- * arguments, and maintains a record of results (either successful returns or thrown errors).
974
+ * This private method handles the actual invocation of the mock function and manages all
975
+ * state trackings.
976
+ *
977
+ * This method is central to the mock's functionality, enabling call tracking,
978
+ * result recording, and the execution of custom implementations.
848
979
  *
849
980
  * @since 1.0.0
850
981
  */
851
982
  private invoke;
852
983
  /**
853
- * Invokes a function within a specific context and with provided arguments.
854
- *
855
- * @template Context The type of the context in which the function is invoked.
856
- * @template Args The type of the arguments passed to the function.
857
- * @template ReturnType The type of the value that the invoked function returns.
984
+ * Handles property access for the mock function proxy.
858
985
  *
859
- * @param target - The instance of the class containing the method to be invoked.
860
- * @param thisArg - The context object that will be bound to the invoked function.
861
- * @param argumentsList - The list of arguments to pass to the invoked function.
862
- * @returns The result of the invoked function or `undefined` if no value is returned.
986
+ * @param target - The mock function instance
987
+ * @param property - The property name or symbol being accessed
988
+ * @returns The property value from either the mock or the original implementation
863
989
  *
864
990
  * @remarks
865
- * This method modifies the state of the `target` instance by adding the `thisArg`
866
- * to the `target.state.instances` array before invoking the function.
991
+ * This private method is used as the 'get' trap for the Proxy surrounding the mock function.
992
+ * It provides property access fallback behavior - first checking if the property exists
993
+ * on the mock itself, and if not, retrieving it from the original implementation.
994
+ *
995
+ * This enables the mock to maintain its own properties while still allowing access to
996
+ * properties from the original function, providing a more transparent mocking experience.
867
997
  *
868
998
  * @since 1.0.0
869
999
  */
870
- private invokeFunction;
1000
+ private invokeGet;
871
1001
  /**
872
- * Invokes a class method on the provided target with specified arguments and a new target.
1002
+ * Handles constructor invocation when the mock is used with 'new'.
873
1003
  *
874
- * @template Args - The type of arguments to be passed to the invoked method.
875
- *
876
- * @param target - The object on which the class method is invoked.
877
- * @param argArray - The array of arguments to pass to the invoked method.
878
- * @param newTarget - The new object used as the invocation context.
879
- * @returns The result of the invocation, typically an object. If the result is not an object,
880
- * the `newTarget` is returned instead.
1004
+ * @param target - The mock function instance
1005
+ * @param argArray - The arguments passed to the constructor
1006
+ * @param newTarget - The constructor that was directly invoked
1007
+ * @returns The constructed instance
881
1008
  *
882
1009
  * @remarks
883
- * This method ensures that the result is stored in the `instances` array of the target's state
884
- * if it is detected as a proper class instance. Otherwise, the `newTarget` is registered.
1010
+ * This method is used as the 'construct' trap for the Proxy surrounding the mock function.
1011
+ * It delegates to the `invoke` method to handle the actual function call, then tracks the
1012
+ * resulting instance in the mock's state for later verification.
1013
+ *
1014
+ * The method handles both cases where the constructor returns an object (which becomes the
1015
+ * instance) and where it doesn't (in which case the newTarget becomes the instance).
885
1016
  *
886
1017
  * @since 1.0.0
887
1018
  */
888
1019
  private invokeClass;
1020
+ /**
1021
+ * Handles function invocation when the mock is called.
1022
+ *
1023
+ * @param target - The mock function instance
1024
+ * @param thisArg - The 'this' context for the function call
1025
+ * @param argumentsList - The arguments passed to the function
1026
+ * @returns The result of the function invocation
1027
+ *
1028
+ * @remarks
1029
+ * This method is used as the 'apply' trap for the Proxy surrounding the mock function.
1030
+ * It captures the calling context in the mock's state for later verification, then
1031
+ * delegates to the `invoke` method to handle the actual function call logic.
1032
+ *
1033
+ * This method is called whenever the mock function is invoked as a regular function
1034
+ * (not as a constructor).
1035
+ *
1036
+ * @since 1.0.0
1037
+ */
1038
+ private invokeFunction;
889
1039
  }
890
1040
 
891
1041
  /**
@@ -908,6 +1058,9 @@ interface BoundInterface<Context = unknown | null | undefined, Args = Array<unkn
908
1058
  __boundArgs?: Args;
909
1059
  }
910
1060
 
1061
+ /**
1062
+ * Import will remove at compile time
1063
+ */
911
1064
  /**
912
1065
  * Represents the possible result types of a mock function invocation.
913
1066
  *
@@ -967,35 +1120,35 @@ interface MockInvocationResultInterface<T> {
967
1120
  *
968
1121
  * @since 1.0.0
969
1122
  */
970
- interface MocksStateInterface<ReturnType, Args extends Array<unknown> = [], Context = unknown> {
1123
+ interface MocksStateInterface<F extends FunctionType> {
971
1124
  /**
972
1125
  * An array that holds the arguments for each invocation made to the mock.
973
1126
  * Each entry corresponds to the arguments passed during a single call to the mock function.
974
1127
  *
975
1128
  * @since 1.0.0
976
1129
  */
977
- calls: Array<Args>;
1130
+ calls: Array<Parameters<F>>;
978
1131
  /**
979
1132
  * The arguments passed to the mock during its most recent invocation.
980
1133
  * Returns `undefined` if the mock has not been called yet.
981
1134
  *
982
1135
  * @since 1.0.0
983
1136
  */
984
- lastCall?: Args;
1137
+ lastCall?: Parameters<F>;
985
1138
  /**
986
1139
  * An array of contexts (`this` values) for each invocation made to the mock.
987
1140
  * Each entry corresponds to the context in which the mock was called.
988
1141
  *
989
1142
  * @since 1.0.0
990
1143
  */
991
- contexts: Array<Context>;
1144
+ contexts: Array<ThisParameterType<F>>;
992
1145
  /**
993
1146
  * An array of all object instances created by the mock.
994
1147
  * Each entry represents an instance was instantiated during the mocks invocations.
995
1148
  *
996
1149
  * @since 1.0.0
997
1150
  */
998
- instances: Array<Context>;
1151
+ instances: Array<ThisParameterType<F>>;
999
1152
  /**
1000
1153
  * An array of invocation order indices for the mock.
1001
1154
  * xJet assigns an index to each call, starting from 1, to track the order in which mocks are invoked within a test file.
@@ -1009,8 +1162,39 @@ interface MocksStateInterface<ReturnType, Args extends Array<unknown> = [], Cont
1009
1162
  *
1010
1163
  * @since 1.0.0
1011
1164
  */
1012
- results: Array<MockInvocationResultInterface<ReturnType>>;
1165
+ results: Array<MockInvocationResultInterface<ReturnType<F>>>;
1013
1166
  }
1167
+ /**
1168
+ * A utility type that extracts the signature of a function and allows it to be reused in an implementation.
1169
+ *
1170
+ * @remarks
1171
+ * This type creates a representation of a function's signature based on its return type, parameters, and
1172
+ * `this` context. It's particularly useful for creating mock implementations, decorators, or wrappers
1173
+ * that need to maintain the same signature as the original function.
1174
+ *
1175
+ * By using this type, you can ensure type safety when implementing functions that need to match
1176
+ * an existing function's signature exactly, including its return type, parameter types, and `this` binding.
1177
+ *
1178
+ * @typeParam F - The original function type to extract the signature from
1179
+ *
1180
+ * @example
1181
+ * ```ts
1182
+ * // Original function
1183
+ * function greet(name: string): string {
1184
+ * return `Hello, ${name}!`;
1185
+ * }
1186
+ *
1187
+ * // Implementation with the same signature
1188
+ * const mockGreet: ImplementationType<typeof greet> = function(name) {
1189
+ * return `Mocked greeting for ${name}`;
1190
+ * };
1191
+ *
1192
+ * // Both functions now have the exact same type signature
1193
+ * ```
1194
+ *
1195
+ * @since 1.2.2
1196
+ */
1197
+ type ImplementationType<F extends FunctionType> = FunctionLikeType<ReturnType<F>, Parameters<F>, ThisParameterType<F>>;
1014
1198
 
1015
1199
  /**
1016
1200
  * A base error class that extends the standard Error class with enhanced JSON serialization and location tracking
@@ -1091,16 +1275,134 @@ declare class ExecutionError extends Error {
1091
1275
  toJSON(): Record<string, unknown>;
1092
1276
  }
1093
1277
 
1278
+ /**
1279
+ * Import will remove at compile time
1280
+ */
1281
+ /**
1282
+ * Recursively searches for a specific element within an object or its nested properties.
1283
+ *
1284
+ * @param target - The object to search within.
1285
+ * @param element - The value to find within the target object or its nested properties.
1286
+ * @param key - Optional specific key to search for within the target object.
1287
+ * @param maxDepth - Maximum recursion depth to prevent infinite loops, defaults to 3.
1288
+ * @returns A {@link DeepSearchInterface} object containing parent and key if found, or null if not found.
1289
+ *
1290
+ * @remarks
1291
+ * This utility performs a depth-first search through an object's properties to locate a specific value
1292
+ * or a property with a specific key. It maintains a set of visited objects to prevent circular reference issues.
1293
+ *
1294
+ * The search process:
1295
+ * - Tracks visited objects to avoid circular references
1296
+ * - Searches by exact reference equality for the element
1297
+ * - Handles errors during property access
1298
+ * - Limits search depth to prevent stack overflow
1299
+ * - Can find elements by exact key name (when the `key` parameter is provided)
1300
+ *
1301
+ * @example
1302
+ * ```ts
1303
+ * const obj = {
1304
+ * a: 1,
1305
+ * b: {
1306
+ * c: 'test',
1307
+ * d: [1, 2, { e: 'target' }]
1308
+ * }
1309
+ * };
1310
+ *
1311
+ * // Find by value
1312
+ * const result = deepSearchObject(obj, 'target');
1313
+ * // result: { parent: { e: 'target' }, key: 'e' }
1314
+ *
1315
+ * // Find by key name
1316
+ * const byKey = deepSearchObject(obj, null, 'c');
1317
+ * // byKey: { parent: { c: 'test', d: [...] }, key: 'c' }
1318
+ * ```
1319
+ *
1320
+ * @see DeepSearchInterface
1321
+ * @since 1.0.0
1322
+ */
1323
+ declare function deepSearchObject(target: Record<string | symbol, unknown>, element: unknown, key?: string, maxDepth?: number): DeepSearchInterface | null;
1324
+ /**
1325
+ * Resolves property references that may be affected by ESBuild's `__toESM` transformation.
1326
+ *
1327
+ * @remarks
1328
+ * This function handles a specific issue with ESBuild's module transformation where Node.js
1329
+ * built-in modules (like 'fs', 'http', etc.) are wrapped with getter descriptors that aren't
1330
+ * configurable. This causes problems when trying to mock or modify these modules in testing.
1331
+ *
1332
+ * When ESBuild transforms CommonJS modules to ESM, it creates non-configurable getter properties
1333
+ * on the module object. This function detects such cases and returns a reference to the original
1334
+ * underlying object instead, making the property accessible for mocking or modification.
1335
+ *
1336
+ * @param parent - The object containing the property to resolve
1337
+ * @param key - The property name or symbol to resolve
1338
+ * @returns A {@link DeepSearchInterface} pointing to either the original object or the
1339
+ * underlying object in case of non-configurable ESBuild transformations
1340
+ *
1341
+ * @example
1342
+ * ```ts
1343
+ * // When working with an ESBuild transformed fs module
1344
+ * import * as fs from 'fs';
1345
+ *
1346
+ * // Normal access would use a non-configurable getter
1347
+ * // Making it impossible to mock
1348
+ * const originalRef = { parent: fs, key: 'readFileSync' };
1349
+ *
1350
+ * // This function resolves to the underlying object
1351
+ * const mockableRef = getOwnProperty(fs, 'readFileSync');
1352
+ * // Now we can mock it: mockableRef.parent[mockableRef.key] = mockFn;
1353
+ * ```
1354
+ *
1355
+ * @since 1.2.2
1356
+ */
1357
+ declare function getOwnProperty(parent: Record<string | symbol, unknown>, key: string | symbol): DeepSearchInterface;
1358
+
1359
+ /**
1360
+ * Interface representing the result of a deep object search operation.
1361
+ *
1362
+ * @remarks
1363
+ * This interface provides a structured way to return the results of an object traversal
1364
+ * search, containing both the parent object and the specific key where a target value was found.
1365
+ * It allows callers to not only determine if a value was found, but also access its
1366
+ * containing object and property name.
1367
+ *
1368
+ * The interface is typically used in deep search algorithms that need to return both
1369
+ * the location of a found item and provide access to its context.
1370
+ *
1371
+ * @example
1372
+ * ```ts
1373
+ * // Example result from a search operation
1374
+ * const result: DeepSearchInterface = {
1375
+ * parent: { id: 123, name: 'example' },
1376
+ * key: 'name'
1377
+ * };
1378
+ *
1379
+ * // Accessing the found value through the result
1380
+ * const foundValue = result.parent[result.key]; // 'example'
1381
+ * ```
1382
+ *
1383
+ * @since 1.2.2
1384
+ */
1385
+ interface DeepSearchInterface {
1386
+ /**
1387
+ * The property key (name) where the searched element was found.
1388
+ *
1389
+ * @since 1.2.2
1390
+ */
1391
+ key: string | symbol;
1392
+ /**
1393
+ * The parent object containing the found element.
1394
+ *
1395
+ * @since 1.2.2
1396
+ */
1397
+ parent: Record<string | symbol, unknown>;
1398
+ }
1399
+
1094
1400
  /**
1095
1401
  * Import will remove at compile time
1096
1402
  */
1097
1403
  /**
1098
1404
  * Imports
1099
1405
  */
1100
- declare const proxyRegistry: WeakMap<object, {
1101
- proxy: unknown;
1102
- spies: Map<PropertyKey, MockState>;
1103
- }>;
1104
1406
  /**
1105
1407
  * Checks if a property on an object is provided via a proxy mechanism rather than directly defined.
1106
1408
  *
@@ -1142,269 +1444,196 @@ declare const proxyRegistry: WeakMap<object, {
1142
1444
  */
1143
1445
  declare function isProxyProperty<T extends object>(obj: T, key: keyof T): boolean;
1144
1446
  /**
1145
- * Creates a spy on a property accessed via a proxy getter, allowing interception
1146
- * and monitoring of property access operations.
1447
+ * Determines if a value is a mock proxy created by the mocking system.
1147
1448
  *
1148
- * @template T - The type of the target object containing the proxy
1149
- * @template K - The type of property key being spied on
1449
+ * @param value - The value to check
1450
+ * @returns `true` if the value is a mock proxy, `false` otherwise
1150
1451
  *
1151
- * @param target - The object containing the property to spy on
1152
- * @param key - The property key to intercept access to
1153
- * @param method - The method to execute when the property is accessed
1154
- * @returns A {@link MockState} instance that tracks interactions with the property
1452
+ * @remarks
1453
+ * This function checks if an object has the internal `__isMockProxy__` symbol property
1454
+ * which is added to all mock proxy objects created by the mocking framework.
1155
1455
  *
1156
- * @throws Error - If the target is not part of any global object
1456
+ * Mock proxies are specialized proxy objects that intercept property access
1457
+ * and method calls while providing mocking capabilities.
1157
1458
  *
1158
1459
  * @example
1159
1460
  * ```ts
1160
- * // Create an object with dynamic property access
1161
- * const user = new Proxy({}, {
1162
- * get(target, prop) {
1163
- * if (prop === 'name') return 'John';
1164
- * return target[prop];
1165
- * }
1166
- * });
1167
- *
1168
- * // Spy on the 'name' property
1169
- * const nameSpy = spyOnProxyGet(user, 'name', () => 'Jane');
1170
- *
1171
- * // Now accessing user.name returns 'Jane' and the access is tracked
1172
- * console.log(user.name); // 'Jane'
1173
- * expect(nameSpy).toHaveBeenCalled();
1461
+ * const regularObject = { name: 'Test' };
1462
+ * const mockObject = createMock({ name: 'Test' });
1174
1463
  *
1175
- * // Restore original behavior
1176
- * nameSpy.mockRestore();
1177
- * console.log(user.name); // 'John'
1464
+ * isMockProxy(regularObject); // false
1465
+ * isMockProxy(mockObject); // true
1178
1466
  * ```
1179
1467
  *
1180
- * @see MockState
1181
- * @see getParentObject
1182
- *
1183
- * @since 1.2.0
1468
+ * @since 1.2.2
1184
1469
  */
1185
- declare function spyOnProxyGet<T extends object, K extends keyof T>(target: T, key: K, method: unknown): MockState;
1470
+ declare function isMockProxy(value: Record<symbol, unknown>): boolean;
1186
1471
  /**
1187
- * Creates a spy on a specified static method or static property of a target class (not a class instance).
1188
- * Useful for mocking behavior during testing.
1472
+ * Creates a mock proxy that intercepts property access on an object.
1189
1473
  *
1190
- * @template Target - The type of the target class.
1191
- * @template Key - The static method or static property key on the target object to spy on.
1474
+ * @template T - The type of the target object being proxied
1475
+ * @param target - The object to be proxied
1476
+ * @returns A MockProxyInterface that intercepts property access on the target
1192
1477
  *
1193
- * @param target - The object on which to spy.
1194
- * @param key - The key of the method or property of the target to spy on.
1195
- * @returns If the spied-on property is a function, returns a `MockState` object for the function,
1196
- * allowing tracking of calls and modifying the return value or behavior.
1197
- * Otherwise, returns a `MockState` object for the property, enabling tracking and manipulation of its value.
1478
+ * @remarks
1479
+ * This function creates a proxy around an object that allows for interception
1480
+ * and customization of property access. The proxy maintains an internal state
1481
+ * that tracks mocked properties and provides mechanisms for customizing getter behavior.
1198
1482
  *
1199
- * @throws Error Throws an error if the `target` is a primitive value.
1200
- * @throws Error Throws an error if `key` is null or undefined.
1201
- * @throws Error Throws an error if the specified property does not exist on the target object.
1483
+ * The proxy implements special properties:
1484
+ * - `__isMockProxy__`: Used to identify mock proxy objects
1485
+ * - `__MockMap__`: Provides access to the internal state for managing mocks
1202
1486
  *
1203
- * @remarks
1204
- * This function is commonly used in testing environments to replace or monitor functionality without
1205
- * altering the actual logic in the source code. It provides fine-grained control over target behavior.
1487
+ * Property access behavior:
1488
+ * 1. First checks if a custom getter is defined and uses it if available
1489
+ * 2. Then checks if the property has a specific mock implementation
1490
+ * 3. Falls back to the original property on the target object
1206
1491
  *
1207
1492
  * @example
1208
1493
  * ```ts
1209
- * class ClassTest {
1210
- * static name: string = 'ClassTest';
1494
+ * const user = { name: 'John', getAge: () => 30 };
1495
+ * const mockUser = createMockProxy(user);
1211
1496
  *
1212
- * static x(param: string) {
1213
- * console.log(`original static x ${ param }`);
1214
- * }
1215
- * }
1216
- *
1217
- * const spy1 = xJet.spyOn(ClassTest, 'name');
1218
- * const spy2 = xJet.spyOn(ClassTest, 'x');
1497
+ * // Access original property
1498
+ * console.log(mockUser.name); // "John"
1219
1499
  *
1220
- * spy1.mockReturnValueOnce('Mock name');
1221
- * spy2.mockImplementationOnce((param: string) => {
1222
- * console.log(`Mock x ${ param }`);
1223
- * });
1224
- *
1225
- * console.log(ClassTest.name); // Mock name
1226
- * console.log(ClassTest.name); // ClassTest
1500
+ * // Add a mock for a property
1501
+ * const mockMap = mockUser.__MockMap__;
1502
+ * mockMap.mocks.set('getAge', () => 25);
1227
1503
  *
1228
- * ClassTest.x('test1'); // Mock x test1
1229
- * ClassTest.x('test2'); // original static x test2
1504
+ * // Now returns the mock implementation
1505
+ * console.log(mockUser.getAge()); // 25
1230
1506
  * ```
1231
1507
  *
1232
- * @see FunctionType
1233
- * @see KeysExtendingConstructorType
1234
- *
1235
- * @since 1.0.0
1508
+ * @since 1.2.2
1236
1509
  */
1237
- declare function spyOnImplementation<Target, Key extends KeysExtendingConstructorType<Target>>(target: Target, key: Key): Target[Key] extends FunctionType ? MockState<ReturnType<Target[Key]>, Parameters<Target[Key]>, Target> : MockState<Target[Key], [], Target>;
1510
+ declare function createMockProxy<T extends object>(target: T): MockProxyInterface;
1238
1511
  /**
1239
- * Creates a mock spy on the specified method or constructor of the target object.
1240
- *
1241
- * @template Target The type of the target object.
1242
- * @template Key The type of the method or constructor key on the target object.
1512
+ * Creates a spy on a property access for a proxied object.
1243
1513
  *
1244
- * @param target - The object whose method or constructor needs to be spied on.
1245
- * @param key - The property key of the method or constructor to spy on.
1246
- * @return A mock state representing the spied method or constructor if the key corresponds to a constructor type;
1247
- * otherwise, throws a type error.
1514
+ * @template T - The type of the target object
1515
+ * @template K - The key of the property to spy on
1248
1516
  *
1249
- * @throws Error Throws an error if the `target` is a primitive value.
1250
- * @throws Error Throws an error if `key` is null or undefined.
1251
- * @throws Error Throws an error if the specified property does not exist on the target object.
1517
+ * @param target - The proxy object containing the property to spy on
1518
+ * @param prop - The name of the property to spy on
1519
+ * @returns A MockState object wrapping the property access
1252
1520
  *
1253
1521
  * @remarks
1254
- * This method is typically used for testing purposes to observe or manipulate calls to the method or constructor of an object.
1255
- * The returned mock state may allow additional configuration, such as altering its behavior or tracking calls.
1522
+ * This specialized spy function is designed to work with properties accessed through proxy objects.
1523
+ * It handles the complexities of intercepting property access in proxied objects by:
1524
+ *
1525
+ * 1. Locating the proxy object in the global scope if needed
1526
+ * 2. Converting a normal object to a mock proxy if it isn't already one
1527
+ * 3. Setting up a spy on the property get operation
1528
+ *
1529
+ * The function ensures proper cleanup by providing a cleanup function that removes
1530
+ * the spy from the proxy's internal mock map when the spy is restored.
1531
+ *
1532
+ * @throws Error - When the target object cannot be found in the global scope
1256
1533
  *
1257
1534
  * @example
1258
1535
  * ```ts
1259
- * const coolObject = {
1260
- * ClassTest: class {
1261
- * constructor(param: number) {
1262
- * console.log('original Constructor');
1263
- * }
1264
- *
1265
- * justAnFunction() {
1266
- * console.log('original justAnFunction');
1267
- * }
1268
- * }
1269
- * };
1536
+ * // With an existing proxy
1537
+ * const proxyObj = createMockProxy({ getData: () => 'data' });
1538
+ * const spy = spyOnProxyGet(proxyObj, 'getData');
1270
1539
  *
1271
- * const spy = xJet.spyOn(coolObject, 'ClassTest');
1272
- * spy.mockImplementationOnce((param: number) => {
1273
- * console.log(`mock Constructor with param: ${ param }`);
1274
- *
1275
- * return <any> {
1276
- * justAnFunction() {
1277
- * console.log('mock justAnFunction');
1278
- * }
1279
- * };
1280
- * });
1540
+ * proxyObj.getData(); // Spy records this call
1541
+ * spy.verify.called(); // Passes
1281
1542
  *
1282
- * const instance = new coolObject.ClassTest(1); // mock Constructor with param: 1
1283
- * instance.justAnFunction(); // mock justAnFunction
1543
+ * // With a normal object (will be converted to proxy)
1544
+ * const obj = { getValue: () => 42 };
1545
+ * const valueSpy = spyOnProxyGet(obj, 'getValue');
1284
1546
  *
1285
- * const instance2 = new coolObject.ClassTest(2); // original Constructor
1286
- * instance2.justAnFunction(); // original justAnFunction
1547
+ * obj.getValue(); // Spy records this call
1548
+ * valueSpy.verify.called(); // Passes
1287
1549
  * ```
1288
1550
  *
1289
- * @see ConstructorType
1290
- * @see ConstructorKeysType
1291
- *
1292
- * @since 1.0.0
1551
+ * @since 1.2.2
1293
1552
  */
1294
- declare function spyOnImplementation<Target, Key extends ConstructorKeysType<Target>>(target: Target, key: Key): Target[Key] extends ConstructorLikeType ? MockState<InstanceType<Target[Key]>, ConstructorParameters<Target[Key]>, Target> : never;
1553
+ declare function spyOnProxyGet<T extends Record<string | symbol, unknown>, K extends keyof T>(target: T, prop: K): MockState;
1295
1554
  /**
1296
- * Creates a spy on a specific method or property of the given target object.
1555
+ * Creates a spy on a method or property of an object.
1297
1556
  *
1298
- * @template Target - The type of the target object to spy on.
1299
- * @template Key - The key of the property or method to spy on within the target object.
1557
+ * @template T - The type of the target object
1558
+ * @template K - The key of the property or method to spy on
1300
1559
  *
1301
- * @param target - The target object containing the property or method to be spied upon.
1302
- * @param key - The name of the property or method on the target object to spy on.
1303
- * @returns If the spied target is a function, it returns a `MockState` object to observe calls and arguments of the function.
1304
- * Otherwise, it returns a `MockState` object to observe the value or state of the property.
1560
+ * @param target - The object containing the method or property to spy on
1561
+ * @param key - The name of the method or property to spy on
1562
+ * @returns A MockState object wrapping the original method or property
1305
1563
  *
1306
- * @throws Error Throws an error if the `target` is a primitive value.
1307
- * @throws Error Throws an error if `key` is null or undefined.
1308
- * @throws Error Throws an error if the specified property does not exist on the target object.
1564
+ * @remarks
1565
+ * This function creates a spy that wraps around an existing method or property on an object.
1566
+ * The spy tracks all calls to the method or access to the property while still executing the original functionality.
1309
1567
  *
1310
- * @remarks This method is commonly used in test environments to monitor and assert interactions with a specific property
1311
- * or method on an object. The returned `MockState` can be used to retrieve call history or observe mutations.
1568
+ * - For methods: The spy preserves the original `this` context and passes all arguments to the original method
1569
+ * - For properties: The spy intercepts property access and returns the original value
1312
1570
  *
1313
1571
  * @example
1314
1572
  * ```ts
1315
- * const coolObject = {
1316
- * myMethod() {
1317
- * return 'Original myMethod';
1318
- * },
1319
- * coolString: 'Original coolString'
1573
+ * // Spying on a method
1574
+ * const user = {
1575
+ * getName: (prefix: string) => prefix + ' John'
1320
1576
  * };
1577
+ * const spy = xJet.spyOn(user, 'getName');
1321
1578
  *
1322
- * const spy = xJet.spyOn(coolObject, 'coolString');
1323
- * const spy2 = xJet.spyOn(coolObject, 'myMethod');
1324
- *
1325
- * spy.mockImplementationOnce(() => 'mock coolString');
1326
- * spy2.mockImplementationOnce(() => 'mock myMethod string');
1327
- *
1328
- * console.log(coolObject.coolString); // mock coolString
1329
- * console.log(coolObject.coolString); // Original coolString
1330
- * console.log(coolObject.myMethod()); // mock myMethod string
1331
- * console.log(coolObject.myMethod()); // Original myMethod
1579
+ * user.getName('Mr.'); // Returns "Mr. John"
1332
1580
  * ```
1333
1581
  *
1334
- * @see FunctionType
1335
- *
1336
1582
  * @since 1.0.0
1337
1583
  */
1338
- declare function spyOnImplementation<Target, Key extends keyof Target>(target: Target, key: Key): Target[Key] extends FunctionType ? MockState<ReturnType<Target[Key]>, Parameters<Target[Key]>, ThisParameterType<Target[Key]>> : MockState<Target[Key] | void, [Target[Key]], ThisParameterType<Target[Key]>>;
1584
+ declare function spyOnImplementation<T extends object, K extends keyof T>(target: T, key: K): T[K] extends FunctionType ? MockState<(this: ThisParameterType<T[K]>, ...args: Parameters<T[K]>) => PartialResolvedType<ReturnType<T[K]>>> : MockState<() => T[K]>;
1339
1585
 
1340
1586
  /**
1341
- * Import will remove at compile time
1342
- */
1343
- /**
1344
- * A utility type that removes all index signatures (string and number keys) from the given type `T`.
1345
- * This results in a new type that retains only explicitly defined properties.
1346
- *
1347
- * @template T - The type from which index signatures are to be removed.
1348
- *
1349
- * @remarks
1350
- * This type is useful for filtering out index signatures from types, especially when working
1351
- * with mapped or dynamic types where indexable properties are not desired.
1352
- * When an object has an index signature (e.g., `[key: string]: any`), TypeScript assumes that all
1353
- * possible string or number keys exist on the object. This utility type filters out such keys,
1354
- * leaving only explicitly defined properties.
1355
- *
1356
- * @see https://stackoverflow.com/a/66252656/4536543
1357
- *
1358
- * @since 1.0.0
1359
- */
1360
- type RemoveIndexType<T> = {
1361
- [P in keyof T as string extends P ? never : number extends P ? never : P]: T[P];
1362
- };
1363
- /**
1364
- * A utility type that maps the keys of a given type `T` whose properties are constructor types.
1365
- *
1366
- * This type iterates over the properties of `RemoveIndexType<T>`,
1367
- * retaining only those keys where the value matches a constructor type.
1368
- *
1369
- * @template T - The target type from which constructor-like properties are to be extracted.
1370
- *
1371
- * @remarks
1372
- * This type is designed to filter out keys of a given type `T` to include only those that are associated with constructor functions.
1373
- * It leverages mapped types along with conditional type checks to achieve this functionality.
1374
- *
1375
- * @since 1.0.0
1376
- */
1377
- type PropertiesWithConstructorsType<T> = {
1378
- [Key in keyof RemoveIndexType<T> as RemoveIndexType<T>[Key] extends ConstructorType ? Key : never]: RemoveIndexType<T>[Key];
1379
- };
1380
- /**
1381
- * A utility type that extracts the keys of the provided type `T` that correspond
1382
- * to properties with constructor types, removing any index signatures.
1383
- *
1384
- * @template T - The object type from which constructor property keys are extracted.
1587
+ * Interface representing the internal state of a mock proxy.
1385
1588
  *
1386
1589
  * @remarks
1387
- * This type is useful for narrowing down a type to only the keys representing
1388
- * properties with constructor functions (e.g., classes) while excluding index signatures.
1590
+ * This interface defines the structure for storing and managing the internal state
1591
+ * of mock proxies, including mock implementations and custom property access behavior.
1389
1592
  *
1390
- * @since 1.0.0
1593
+ * @since 1.2.2
1391
1594
  */
1392
- type ConstructorKeysType<T> = RemoveIndexType<keyof PropertiesWithConstructorsType<T>>;
1595
+ interface MockProxyStateInterface {
1596
+ /**
1597
+ * Map storing mock implementations for specific properties.
1598
+ * Keys are property names, values are the mock implementations.
1599
+ *
1600
+ * @since 1.2.2
1601
+ */
1602
+ mocks: Map<PropertyKey, unknown>;
1603
+ /**
1604
+ * Optional custom getter function that overrides default property access behavior.
1605
+ * When provided, this function is called for all property access on the mock proxy.
1606
+ *
1607
+ * @since 1.2.2
1608
+ */
1609
+ customGetter: ((target: object, prop: PropertyKey, receiver: unknown) => unknown) | null;
1610
+ }
1393
1611
  /**
1394
- * A utility type that extracts the keys of a type `T` if `T` extends a constructor type.
1395
- * If `T` does not extend a constructor type, it resolves to `never`.
1396
- *
1397
- * @template T - The type to check and extract keys from.
1398
- *
1399
- * @param T - The generic type parameter which is evaluated against a constructor type.
1612
+ * Interface representing a mock proxy object.
1400
1613
  *
1401
1614
  * @remarks
1402
- * This type is particularly useful when working with class-like or constructor-based types.
1403
- * It further applies `RemoveIndexType` to exclude index signatures from the resulting keys.
1615
+ * A `MockProxyInterface` defines the structure of objects that have been
1616
+ * wrapped by a mocking proxy system. These proxies intercept property access
1617
+ * and allow for dynamic replacement or monitoring of object properties.
1404
1618
  *
1405
- * @since 1.0.0
1619
+ * @since 1.2.2
1406
1620
  */
1407
- type KeysExtendingConstructorType<T> = T extends ConstructorType ? keyof RemoveIndexType<T> : never;
1621
+ interface MockProxyInterface extends Record<PropertyKey, unknown> {
1622
+ /**
1623
+ * A boolean flag that indicates this object is a mock proxy.
1624
+ * Used for type checking and identification of mock objects.
1625
+ *
1626
+ * @since 1.2.2
1627
+ */
1628
+ readonly __isMockProxy__?: true;
1629
+ /**
1630
+ * Provides access to the internal state of the mock proxy,
1631
+ * including mapped mock implementations and custom getter functions.
1632
+ *
1633
+ * @since 1.2.2
1634
+ */
1635
+ readonly __MockMap__?: MockProxyStateInterface;
1636
+ }
1408
1637
 
1409
1638
  /**
1410
1639
  * Import will remove at compile time