New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@corez/mock

Package Overview
Dependencies
Maintainers
0
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@corez/mock - npm Package Compare versions

Comparing version 0.9.1 to 0.10.0

src/utils/clone.ts

41

dist/cjs/index.d.ts

@@ -120,3 +120,3 @@ /**

*/
inPlace?: boolean;
inplace?: boolean;
/**

@@ -155,6 +155,16 @@ * Partial implementation to override specific properties or methods

* When false, only mocks the top level object's own methods
* Only applies when inPlace is false
* Only applies when inplace is false
* @default false
*/
prototypeChain?: boolean;
/**
* Glob patterns for methods/properties to mock
* Supports ! prefix for exclusion
* Examples:
* - ['get*'] - mock all methods starting with 'get'
* - ['!private*'] - exclude all methods starting with 'private'
* - ['handle{Get,Post}*'] - mock all methods starting with handleGet or handlePost
* @default undefined - mocks everything except constructor
*/
patterns?: string[];
}

@@ -179,7 +189,24 @@ /**

/**
* Controls whether to mock static class members
* Includes static methods, properties, and getters/setters
* Glob patterns for methods/properties to mock
* Supports ! prefix for exclusion
* Examples:
* - ['get*'] - mock all methods starting with 'get'
* - ['!private*'] - exclude all methods starting with 'private'
* - ['handle{Get,Post}*'] - mock all methods starting with handleGet or handlePost
* @default undefined - mocks everything except constructor
*/
patterns?: string[];
/**
* Controls static member mocking
* Can be boolean to mock all/none static members
* Or array of glob patterns with ! prefix for exclusion
* @default false
*/
static?: boolean;
static?: boolean | string[];
/**
* Controls whether to mock inherited methods
* When false, only mocks methods defined directly on the class
* @default true
*/
inheritance?: boolean;
}

@@ -279,6 +306,2 @@ /**

/**
* Creates a factory-based mock class that automatically mocks instances on construction
*/
factory<T extends Constructor<any>>(target: T, options?: ObjectMockOptions): T;
/**
* Casts a partial implementation to a complete mock

@@ -285,0 +308,0 @@ */

{
"name": "@corez/mock",
"version": "0.9.1",
"version": "0.10.0",
"description": "A powerful and flexible TypeScript mocking library for testing",

@@ -55,2 +55,3 @@ "keywords": [

"@types/jest": "^29.5.14",
"@types/micromatch": "^4.0.9",
"@types/node": "^22.10.5",

@@ -68,2 +69,3 @@ "@typescript-eslint/eslint-plugin": "^8.19.1",

"jest": "^29.7.0",
"micromatch": "^4.0.8",
"prettier": "^3.4.2",

@@ -70,0 +72,0 @@ "release-it": "^18.1.1",

@@ -10,13 +10,15 @@ # @corez/mock

## 目录
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [API Reference](#api-reference)
- [Core APIs](#core-apis)
- [Advanced Usage](#advanced-usage)
- [Mock Options](#mock-options)
- [Best Practices](#best-practices)
- [Debugging](#debugging)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)
- [Debugging Features](#debugging-features)

@@ -57,7 +59,2 @@ ## Features

// Mock an object
interface User {
id: number;
name: string;
}
interface UserService {

@@ -68,13 +65,6 @@ getUser(id: number): Promise<User>;

const userService = mock.obj<UserService>(
{
getUser: async id => ({id, name: 'John'}),
updateUser: async user => {},
},
{
overrides: {
getUser: async id => ({id, name: 'Mock User'}),
},
},
);
const userService = mock.obj<UserService>({
getUser: async id => ({id, name: 'John'}),
updateUser: async user => {},
});

@@ -91,3 +81,2 @@ // Mock a class

// Create a new mock class
const MockDatabase = mock.cls(Database, {

@@ -102,5 +91,5 @@ mockStatic: true,

## Core Concepts
## Core APIs
### Mock Functions
### mock.fn() - Function Mocking

@@ -127,3 +116,3 @@ Create standalone mock functions with full tracking capabilities:

### Mock Objects
### mock.obj() - Object Mocking

@@ -149,43 +138,6 @@ Create mock objects with automatic method tracking:

(userService.getUser as any).mockResolvedValue({id: 1, name: 'Mock'});
// Access call information
const getUserMock = userService.getUser as MockFunction;
console.log(getUserMock.calls.count());
console.log(getUserMock.calls.all());
```
#### Advanced Object Mocking Features
### mock.cls() - Class Mocking
1. **Prototype Chain Mocking**
```typescript
const service = mock.obj(originalService, {
prototypeChain: true, // Will mock methods from entire prototype chain
});
```
2. **Arrow Functions vs Regular Methods** The library automatically detects and handles arrow functions differently to
preserve correct `this` binding:
```typescript
class Service {
regularMethod() {
return this;
}
arrowMethod = () => this;
}
const mockedService = mock.obj(new Service());
// Both methods will maintain correct `this` binding
```
3. **In-Place Mocking**
```typescript
const service = mock.obj(originalService, {
inPlace: true, // Modifies the original object
});
```
### Mock Classes
Create mock classes with automatic method tracking:

@@ -203,13 +155,13 @@

// Create a new mock class
const MockDatabase = mock.cls(Database, {
static: true,
mockStatic: true,
preserveConstructor: true,
});
const db = new MockDatabase();
db.query.mockResolvedValue({rows: []});
// Check if class is mocked
console.log(MockDatabase.__is_mocked__); // true
console.log(MockDatabase[IS_MOCKED]); // true
const db = new MockDatabase();
// Access call information

@@ -220,17 +172,7 @@ const queryMock = db.query as MockFunction;

### Factory Mocking
### mock.factory() - Factory Mocking
Create factory-based mock classes that automatically mock instances on construction:
Create factory-based mock classes that automatically mock instances:
```typescript
class Database {
async connect() {
/* ... */
}
async query(sql: string) {
/* ... */
}
}
// Create a factory mock class
const MockDatabase = mock.factory(Database, {

@@ -242,3 +184,3 @@ prototypeChain: true, // Mock all prototype methods

const db = new MockDatabase();
expect(db.query).toHaveProperty('mock'); // true
expect(db.query).toHaveProperty('mock');

@@ -251,221 +193,9 @@ // Mock implementation

expect(db.query).toHaveBeenCalled();
// In-place mocking
mock.factory(Database, {
inPlace: true, // Modify original class
prototypeChain: true,
});
// Now original class creates mocked instances
const db2 = new Database();
db2.query.mockResolvedValue({rows: []});
```
Key features of factory mocking:
### mock.compose() - Composition Mocking
- Automatic instance mocking on construction
- Proper inheritance handling using `Reflect.construct`
- Support for prototype chain mocking
- In-place modification option
- Automatic spy tracking for all methods
- Preserves constructor behavior
Create mocks from classes, objects, or functions:
### Type Definitions
The library provides comprehensive type definitions for mocked classes:
```typescript
// Mock class type that includes mock markers
type ClsMock<T extends Constructor<any>> = T & {
__is_mocked__: boolean;
[IS_MOCKED]: true;
new (...args: ConstructorParameters<T>): InstanceType<T>;
};
// Usage with type checking
const mockDb: ClsMock<typeof Database> = mock.cls(Database);
if (mockDb.__is_mocked__) {
console.log('Class is mocked');
}
```
## API Reference
### Core APIs
#### `mock.fn<T extends Fn = Fn>(): MockFunction<T>`
Creates a mock function with tracking capabilities:
```typescript
const mockFn = mock.fn<(x: number) => number>();
// Set implementation
mockFn.mockImplementation(x => x * 2);
// Set return value
mockFn.mockReturnValue(42);
// Handle async scenarios
mockFn.mockResolvedValue('result');
mockFn.mockRejectedValue(new Error('failed'));
// Verify calls
expect(mockFn.calls.count()).toBe(1);
expect(mockFn.calls.all()[0].args).toEqual([1]);
```
#### `mock.obj<T extends object>(target: T | undefined, options?: ObjectMockOptions<T>): MockObject<T>`
Creates a mock object with automatic method tracking. Available options:
```typescript
interface ObjectMockOptions<T> {
// If true, modifies the original object instead of creating a clone
inPlace?: boolean;
// If true, mocks methods from the entire prototype chain
prototypeChain?: boolean;
// Override specific properties or methods
overrides?: Partial<T>;
}
```
Key features:
- Deep cloning support using `rfdc`
- Automatic handling of arrow functions vs regular methods
- Prototype chain preservation and mocking
- Property descriptor preservation
- Spy tracking for all methods
#### `mock.cls<T extends Constructor<any>>(target: T, options?: ClassMockOptions<T>): ClsMock<T>`
Creates a mock class with automatic method tracking and type safety:
```typescript
// Create a mock class with options
const MockDatabase = mock.cls(Database, {
// Modify original class instead of creating new one
inPlace: false,
// Preserve original method implementations
preservePrototype: true,
// Call original constructor
preserveConstructor: true,
// Override specific methods
overrides: {
query: async () => [{id: 1}],
},
// Enable debug logging
debug: false,
});
// Type checking and verification
if (MockDatabase.__is_mocked__) {
console.log('Class is properly mocked');
}
// Access mock information
const instance = new MockDatabase();
const queryMock = instance.query as MockFunction;
console.log(queryMock.calls.count());
```
The `ClassMockOptions` interface provides fine-grained control:
```typescript
interface ClassMockOptions<T> {
// Whether to modify the original class
inPlace?: boolean;
// Whether to preserve original method implementations
preservePrototype?: boolean;
// Whether to call original constructor
preserveConstructor?: boolean;
// Method overrides
overrides?: Partial<T>;
// Enable debug logging
debug?: boolean;
}
```
#### `mock.factory<T extends Constructor<any>>(target: T, options?: ObjectMockOptions): T`
Creates a factory-based mock class that automatically mocks instances on construction:
```typescript
// Create a factory mock class
const MockDatabase = mock.factory(Database, {
// Mock all prototype chain methods
prototypeChain: true,
// Modify original class instead of creating new one
inPlace: false,
// Override specific methods
overrides: {
query: async () => [{id: 1}],
},
// Enable debug logging
debug: false,
});
// Each instance is automatically mocked
const db = new MockDatabase();
// Mock implementation
db.query.mockResolvedValue({rows: []});
// Track calls
db.query('SELECT * FROM users');
expect(db.query).toHaveBeenCalled();
```
The factory function provides these key features:
- Automatic instance mocking on construction
- Proper inheritance handling using `Reflect.construct`
- Support for prototype chain mocking
- In-place modification option
- Automatic spy tracking for all methods
- Preserves constructor behavior
Available options:
```typescript
interface FactoryOptions extends ObjectMockOptions {
// When true, mocks all prototype chain methods
prototypeChain?: boolean;
// When true, modifies original class
inPlace?: boolean;
// Override specific methods
overrides?: Partial<T>;
// Enable debug logging
debug?: boolean;
}
```
#### `mock.compose<T extends Fn>(): MockFunction<T>;`
#### `mock.compose<T extends new (...args: any[]) => any>(target: T, options?: {overrides?: DeepPartial<InstanceType<T>>} & Partial<Config>): ClsMock<T>;`
#### `mock.compose<T extends object>(target: T, options?: {overrides?: DeepPartial<T>; replace?: {[K in keyof T]?: T[K] extends Fn ? Fn : never}} & Partial<Config>): T;`
#### `mock.compose<T extends object>(partialImpl: DeepPartial<T>, options?: Partial<Config>): T;`
Creates a mock from a class constructor, object, or function:
```typescript
// Mock a function

@@ -476,8 +206,2 @@ const mockFn = mock.compose<(x: number) => string>();

// Mock a class
class Database {
async query(sql: string) {
/* ... */
}
}
const MockDatabase = mock.compose(Database, {

@@ -490,6 +214,2 @@ overrides: {

// Mock an object
interface Api {
fetch(url: string): Promise<any>;
}
const api = mock.compose<Api>(

@@ -505,19 +225,7 @@ {

);
// Mock with partial implementation
interface ComplexApi {
getUsers(): Promise<User[]>;
getUser(id: number): Promise<User>;
createUser(user: User): Promise<void>;
}
const partialApi = mock.compose<ComplexApi>({
getUsers: async () => [{id: 1, name: 'John'}],
getUser: async id => ({id, name: 'John'}),
});
```
#### `mock.cast<T extends object>(partial: DeepPartial<T>, options?: Partial<Config>): T`
### mock.cast() - Type Casting
Casts a partial implementation to a complete mock:
Cast partial implementations to complete mocks:

@@ -533,3 +241,3 @@ ```typescript

// Only implement the methods we need
// Only implement needed methods
const api = mock.cast<CompleteApi>({

@@ -540,15 +248,9 @@ getUsers: async () => [{id: 1, name: 'John'}],

// All other methods will be automatically mocked
await api.createUser({id: 1, name: 'Test'}); // Works, returns undefined
await api.updateUser({id: 1, name: 'Test'}); // Works, returns undefined
await api.deleteUser(1); // Works, returns undefined
// Access call information
const createUserMock = api.createUser as MockFunction;
expect(createUserMock.calls.count()).toBe(1);
// All other methods automatically mocked
await api.createUser({id: 1, name: 'Test'});
```
#### `mock.replace<T extends object, K extends keyof T>(obj: T, key: K, impl: Fn, options?: Partial<Config>): void`
### mock.replace() - Method Replacement
Replaces methods while preserving original implementation:
Replace methods while preserving original implementation:

@@ -560,3 +262,2 @@ ```typescript

}
async processData(data: any) {

@@ -572,37 +273,63 @@ /* ... */

// Verify the method was replaced
// Verify replacement
expect(await service.getData()).toEqual(['mocked']);
// Original processData method remains unchanged
// Original processData remains unchanged
expect(service.processData).toBeDefined();
// Access call information
const getDataMock = service.getData as unknown as MockFunction;
expect(getDataMock.calls.count()).toBe(1);
// Restore original implementation
// Restore original
mock.restore(service);
```
### Mock Control
## Mock Options
All mocks provide these control methods:
### Base Options
```typescript
// Clear call history
mock.mockClear(); // Clears calls but keeps implementation
All mock types support these basic options:
// Reset completely
mock.mockReset(); // Clears everything
- `debug`: Enable detailed logging (default: false)
- `asyncTimeout`: Maximum time for async operations (default: 5000ms)
// Restore original
mock.mockRestore(); // Restores original implementation
### Function Mock Options
// Access state
mock.calls.all(); // Call arguments with context
mock.calls.count(); // Number of calls
```
- `trackCalls`: Record arguments and return values (default: false)
- `autoSpy`: Create spies for function properties (default: false)
### Object Mock Options
- `inplace`: Modify original object or create new one (default: false)
- `prototypeChain`: Deep clone and mock prototype chain (default: true)
- `overrides`: Override specific properties or methods
### Class Mock Options
- `inplace`: Modify original class or create new one (default: false)
- `preservePrototype`: Preserve prototype chain (default: true)
- `preserveConstructor`: Preserve constructor behavior (default: true)
- `mockStatic`: Mock static members (default: false)
- `overrides`: Override specific methods
## Advanced Usage
### Pattern Matching
Control which methods to mock using glob patterns:
```typescript
const service = mock.obj<Service>(
{
getData: () => Promise.resolve({data: 'test'}),
getDataAsync: () => Promise.resolve({data: 'test'}),
setData: data => {},
setDataAsync: async data => {},
},
{
patterns: [
'get*', // Mock all getter methods
'!setData', // Exclude setData method
],
},
);
```
### Async Mocking

@@ -644,3 +371,3 @@

// Using replace for method replacement
// Using replace
mock.replace(service, 'getUser', async id => ({

@@ -651,3 +378,3 @@ id,

// Using overrides for partial implementation
// Using overrides
const partialService = mock.obj<UserService>(

@@ -663,335 +390,100 @@ {},

## Best Practices
## Debugging
1. **Reset Between Tests**
### Debug Logging
```typescript
beforeEach(() => {
mockFn.mockReset();
// or
mockObj.mockReset();
});
```
Enable detailed logging for troubleshooting:
2. **Type Safety**
```typescript
// Prefer interfaces for better type inference
interface Service {
method(): string;
}
const mock = mock.obj<Service>();
```
3. **Error Handling**
```typescript
// Always test error cases
api.fetch.mockRejectedValue(new Error('Network error'));
await expect(api.fetch()).rejects.toThrow('Network error');
```
4. **Verification**
```typescript
// Verify call count and arguments
expect(mockFn.calls.count()).toBe(1);
expect(mockFn.calls.all()[0].args).toEqual(['expected arg']);
```
5. **Using inPlace**
```typescript
// For objects: Use inPlace when you need to maintain object references
const mockObj = mock.obj(original, {
inPlace: true,
overrides: {
method: () => 'mocked',
},
});
// For classes: Be cautious with inPlace as it affects the original class
const MockClass = mock.cls(Original); // Creates new class by default
// If you need to modify the original class:
const ModifiedClass = mock.cls(Original, {
inPlace: true,
// Remember to restore if needed
});
```
## Troubleshooting
### Common Issues
1. **Mock Not Tracking Calls**
- For functions: Enable `trackCalls` in FunctionMockOptions
- For objects and classes: Method calls are tracked automatically
- Ensure you're accessing the mock properties correctly (e.g., `mock.calls`)
2. **Type Inference Issues**
- Use explicit type parameters with interfaces
- Define complete interfaces for complex types
- Use `as MockFunction<T>` for better type support
3. **Prototype Chain Issues**
- For classes: Use `preservePrototype: true` (default)
- For objects: Use `prototypeChain: true` to mock prototype methods (default)
- For type casting: Use `keepPrototype: true` (default)
4. **inPlace Issues**
- For objects: Use `inPlace: true` if you need to maintain object references
- For classes: Be aware that `inPlace: true` modifies the original class
- Remember to restore mocked objects/classes if needed:
```typescript
const mock = mock.obj(original, {inPlace: true});
// ... use mock ...
mock.restore(); // Restore original implementation
```
- When using `inPlace` with inheritance, ensure proper super calls are preserved
- Consider using a new instance if you don't specifically need to modify the original
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## License
Apache-2.0 - see [LICENSE](LICENSE) for details.
## Mock Options
### Base Options
All mock types support these basic options:
- `debug`: Enables detailed logging of mock operations (default: false)
- `asyncTimeout`: Maximum time to wait for async operations in ms (default: 5000)
### Function Mock Options
Options for mocking functions:
- `trackCalls`: Records arguments, return values, and call count (default: false)
- `autoSpy`: Automatically creates spies for all function properties (default: false)
### Object Mock Options
Options for mocking objects:
- `inPlace`: Controls whether to modify the original object or create a new one (default: false)
- `prototypeChain`: Controls whether to perform deep cloning and mocking of nested objects and prototype chain methods
(default: true)
- `overrides`: Allows overriding specific properties or methods with custom implementations
Example of object mocking with inPlace:
```typescript
// Create a new mock object (default behavior)
const mockObj = mock.obj(original, {
overrides: {
method: () => 'mocked',
},
});
import {debug} from '@corez/mock';
// Modify the original object
const modifiedObj = mock.obj(original, {
inPlace: true,
overrides: {
method: () => 'mocked',
},
});
// Enable debug logging
debug.enable();
// Deep mocking is enabled by default
const deepMockObj = mock.obj(original, {
prototypeChain: true, // this is default
});
```
// Set log level
debug.setLevel('error'); // 'error' | 'warn' | 'info' | 'debug'
### Class Mock Options
Options for mocking classes:
- `inPlace`: Controls whether to modify the original class or create a new one (default: false)
- `preservePrototype`: Controls whether to preserve the prototype chain (default: true)
- `preserveConstructor`: Controls whether to preserve the original constructor behavior (default: true)
- `mockStatic`: Controls whether to mock static class members (default: false)
- `overrides`: Allows overriding specific properties or methods with custom implementations
Example of class mocking with inPlace:
```typescript
// Create a new mock class (default behavior)
const MockClass = mock.cls(Original, {
static: true,
overrides: {
method: () => 'mocked',
},
// Custom handler
debug.setHandler((level, message) => {
console.log(`[MOCK] ${level}: ${message}`);
});
// Modify the original class
const ModifiedClass = mock.cls(Original, {
inPlace: true,
static: true,
overrides: {
method: () => 'mocked',
},
});
```
### Cast Mock Options
### Call Tracking
Options for type casting and partial implementations:
Track and verify method calls:
- `keepPrototype`: Maintains the prototype chain when casting objects (default: true)
## Usage Examples
### Basic Function Mocking
```typescript
import {mock} from '@corez/mock';
// Clear history
mock.mockClear(); // Clears calls but keeps implementation
// Create a mock function
const mockFn = mock.fn<() => string>();
mockFn.mockReturnValue('hello');
// Reset completely
mock.mockReset(); // Clears everything
// Track calls
expect(mockFn()).toBe('hello');
expect(mockFn.mock.calls.length).toBe(1);
```
// Restore original
mock.mockRestore(); // Restores original implementation
### Object Mocking
```typescript
import {mock} from '@corez/mock';
interface User {
name: string;
getId(): number;
}
// Create a mock object
const mockUser = mock.obj<User>({
name: 'Test User',
getId: () => 1,
});
// Override methods
mockUser.getId.mockReturnValue(2);
// Access state
mock.calls.all(); // Call arguments with context
mock.calls.count(); // Number of calls
```
### Class Mocking
## Best Practices
```typescript
import {mock} from '@corez/mock';
1. **Type Safety**
class Database {
connect() {
/* ... */
}
query(sql: string) {
/* ... */
}
}
- Always provide type parameters
- Use interfaces for mock shapes
- Let TypeScript infer return types
// Create a mock class
const MockDatabase = mock.cls(Database, {
mockStatic: true,
preserveConstructor: true,
});
2. **Pattern Matching**
const db = new MockDatabase();
db.query.mockResolvedValue({rows: []});
```
- Use specific patterns for needed methods
- Combine positive and negative patterns
- Group related methods with patterns
### Type Casting
3. **Performance**
```typescript
import {mock} from '@corez/mock';
- Disable prototype chain mocking when not needed
- Use shallow cloning for simple objects
- Clean up mocks after use
interface ComplexType {
data: string;
process(): Promise<void>;
}
4. **Error Handling**
- Test error cases
- Verify error messages
- Handle async errors properly
// Cast partial implementation to full mock
const partial = {data: 'test'};
const mockObj = mock.cast<ComplexType>(partial);
```
## Troubleshooting
## Mock Composition
### Common Issues
### Compose Function Options
1. **Mock Not Tracking Calls**
The `compose` function provides a unified interface for creating mocks of different types (classes, objects, and
functions). It uses a sophisticated type system to provide appropriate options based on the target type.
- Enable `trackCalls` for functions
- Method calls tracked automatically for objects/classes
- Check mock property access
#### Options Structure
2. **Type Inference Issues**
```typescript
type ComposeOptions<T> = BaseMockOptions &
(T extends new (...args: any[]) => any
? ClassMockOptions<InstanceType<T>>
: ObjectMockOptions<T> & {
replace?: {
[K in keyof T]?: T[K] extends Fn ? Fn : never;
};
});
```
- Use explicit type parameters
- Define complete interfaces
- Use `as MockFunction<T>` for better typing
#### Design Decisions
3. **Prototype Chain Issues**
1. **Replace vs Override**
- Use `preservePrototype: true` for classes
- Use `prototypeChain: true` for objects
- Use `keepPrototype: true` for casting
- `replace` is specifically designed for object mocking, allowing direct method replacement
- `override` is used in class mocking for overriding prototype methods
- While they may seem similar, they serve different purposes and contexts
4. **Circular References**
- Use `WeakSet` to track processed objects
- Enable debug logging
- Consider shallow cloning
2. **Type Safety**
## Contributing
- The options type automatically adapts based on the target type
- Class mocks receive `ClassMockOptions`
- Object mocks receive `ObjectMockOptions` with additional `replace` capability
- This ensures type safety while maintaining flexibility
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
3. **Usage Examples**
## License
```typescript
// Class mocking
class Service {
getData(): string {
return 'data';
}
}
const mockService = compose(Service, {
override: {
getData: () => 'mocked',
},
});
// Object mocking with replace
const obj = {
method: () => 'original',
};
const mockObj = compose(obj, {
replace: {
method: () => 'replaced',
},
});
```
4. **Best Practices**
- Use `override` for class method mocking
- Use `replace` for direct object method replacement
- Consider the scope and context when choosing between them
- Avoid mixing `override` and `replace` in the same mock
## Debugging Features
### Debug Options
The library provides comprehensive debugging capabilities through the `debug`
Apache-2.0 - see [LICENSE](LICENSE) for details.

@@ -28,3 +28,3 @@ import {BaseMockOptions, CastMockOptions, ClassMockOptions, FunctionMockOptions, ObjectMockOptions} from './types';

...DEFAULT_BASE_OPTIONS,
inPlace: false,
inplace: false,
prototypeChain: true,

@@ -40,6 +40,7 @@ overrides: {},

...DEFAULT_BASE_OPTIONS,
inPlace: false,
inplace: false,
preservePrototype: true,
preserveConstructor: true,
static: false,
static: true,
inheritance: true,
overrides: {},

@@ -46,0 +47,0 @@ };

@@ -9,3 +9,2 @@ import {

import {cast, cls, compose, fn, obj, replace} from './mocks';
import {factory} from './mocks/factory';
import {MockRegistry} from './registry';

@@ -107,6 +106,2 @@ import {

}
factory<T extends Constructor<any>>(target: T, options: ObjectMockOptions = {}): T {
return factory(target, options);
}
}

@@ -150,4 +145,2 @@

) => globalMock.compose(target, _options),
factory: <T extends Constructor<any>>(target: T, options: ObjectMockOptions = {}) =>
globalMock.factory(target, options),
},

@@ -154,0 +147,0 @@ ) as MockFn;

@@ -18,3 +18,3 @@ import {cls} from '../class';

const MockedClass = cls(CallbackURL, {inPlace: true});
const MockedClass = cls(CallbackURL, {inplace: true});
const instance = new MockedClass();

@@ -21,0 +21,0 @@

@@ -209,3 +209,3 @@ import type {ClsMock, MockFunction} from '../../types';

it('should handle inheritance correctly when inPlace is true', () => {
it('should handle inheritance correctly when inplace is true', () => {
class ExtendedChild extends Base {

@@ -229,3 +229,3 @@ constructor() {

const MockChild = cls(ExtendedChild, {inPlace: true});
const MockChild = cls(ExtendedChild, {inplace: true});
const instance = new MockChild();

@@ -253,3 +253,3 @@

it('should handle static inheritance when inPlace is true', () => {
it('should handle static inheritance when inplace is true', () => {
class StaticBase {

@@ -282,3 +282,3 @@ protected static states = new Map<any, any>();

const MockStaticChild = cls(StaticChild, {inPlace: true, static: true});
const MockStaticChild = cls(StaticChild, {inplace: true, static: true});

@@ -302,3 +302,3 @@ // Verify static inheritance works

it('should handle super calls correctly when inPlace is true', () => {
it('should handle super calls correctly when inplace is true', () => {
class SuperBase {

@@ -339,3 +339,3 @@ protected value: string;

const MockChild = cls(SuperChild, {inPlace: true});
const MockChild = cls(SuperChild, {inplace: true});
const instance = new MockChild('test');

@@ -370,12 +370,157 @@

describe('selective mocking', () => {
it('should allow mocking specific methods', () => {
const MockAnimal = cls(Animal);
const mockAnimal = new MockAnimal('test');
const mockSound = jest.fn(() => 'mocked sound');
class TestService {
private value = 'test';
(mockAnimal.makeSound as MockFunction<() => string>).mockImplementation(mockSound);
expect(mockAnimal.makeSound()).toBe('mocked sound');
expect(mockSound).toHaveBeenCalled();
expect(mockAnimal.name).toBe('test'); // Original getter behavior
getValue() {
return this.value;
}
setValue(value: string) {
this.value = value;
}
getValueAsync() {
return Promise.resolve(this.value);
}
_internalMethod() {
return 'internal';
}
static staticValue = 'static';
static getStaticValue() {
return this.staticValue;
}
static setStaticValue(value: string) {
this.staticValue = value;
}
static _internalStatic() {
return 'internal static';
}
}
it('should allow mocking specific methods using patterns', () => {
const MockClass = cls(TestService, {
patterns: ['get*', '!_*'],
});
const instance = new MockClass();
// Should mock getValue and getValueAsync
expect(instance.getValue).toHaveProperty('mock');
expect(instance.getValueAsync).toHaveProperty('mock');
// Should not mock _internalMethod
expect(instance._internalMethod()).toBe('internal');
// Should not mock setValue (not matched by pattern)
expect(instance.setValue('new')).toBeUndefined();
expect(instance.getValue()).toBe('new');
});
it('should support negation patterns', () => {
const MockClass = cls(TestService, {
patterns: ['*', '!set*', '!_*'],
});
const instance = new MockClass();
// Should mock getValue and getValueAsync
expect(instance.getValue).toHaveProperty('mock');
expect(instance.getValueAsync).toHaveProperty('mock');
// Should not mock setValue and _internalMethod
expect(instance.setValue('new')).toBeUndefined();
expect(instance._internalMethod()).toBe('internal');
});
it('should support static method patterns', () => {
const MockClass = cls(TestService, {
static: ['get*', '!_*'],
});
// Should mock getStaticValue
expect(MockClass.getStaticValue).toHaveProperty('mock');
// Should not mock _internalStatic
expect(MockClass._internalStatic()).toBe('internal static');
// Should not mock setStaticValue
expect(MockClass.setStaticValue('new')).toBeUndefined();
expect(MockClass.staticValue).toBe('new');
});
it('should support boolean static option', () => {
const MockClass = cls(TestService, {
static: true,
});
// Should mock all static methods
expect(MockClass.getStaticValue).toHaveProperty('mock');
expect(MockClass.setStaticValue).toHaveProperty('mock');
expect(MockClass._internalStatic).toHaveProperty('mock');
});
it('should not mock any static methods when static is false', () => {
const MockClass = cls(TestService, {
static: false,
});
// Should not mock any static methods
expect(MockClass.getStaticValue()).toBe('static');
expect(MockClass.setStaticValue('new')).toBeUndefined();
expect(MockClass._internalStatic()).toBe('internal static');
});
it('should respect inheritance option', () => {
class Parent {
parentMethod() {
return 'parent';
}
}
class Child extends Parent {
childMethod() {
return 'child';
}
}
const MockClass = cls(Child, {
inheritance: false,
});
const instance = new MockClass();
// Should mock child method
expect(instance.childMethod).toHaveProperty('mock');
// Should not mock parent method
expect(instance.parentMethod()).toBe('parent');
});
it('should handle complex pattern combinations', () => {
const MockClass = cls(TestService, {
// Mock all get* methods except internal ones
patterns: ['get*', '!_*'],
// Mock all static get* methods except internal ones
static: ['get*', '!_*'],
// Don't mock inherited methods
inheritance: false,
});
const instance = new MockClass();
// Instance methods
expect(instance.getValue).toHaveProperty('mock');
expect(instance.getValueAsync).toHaveProperty('mock');
expect(instance._internalMethod()).toBe('internal');
expect(instance.setValue('new')).toBeUndefined();
// Static methods
expect(MockClass.getStaticValue).toHaveProperty('mock');
expect(MockClass._internalStatic()).toBe('internal static');
expect(MockClass.setStaticValue('new')).toBeUndefined();
});
});

@@ -411,3 +556,3 @@

describe('inPlace option', () => {
describe('inplace option', () => {
class TestClass {

@@ -423,4 +568,4 @@ value: string = 'original';

it('should modify original class when inPlace is true', () => {
const ModifiedClass = cls(TestClass, {inPlace: true});
it('should modify original class when inplace is true', () => {
const ModifiedClass = cls(TestClass, {inplace: true});

@@ -446,4 +591,4 @@ // Verify returned class is the same as original

it('should mark mock class with IS_MOCKED symbol when inPlace is true', () => {
const MockClass = cls(TestClass, {inPlace: true});
it('should mark mock class with IS_MOCKED symbol when inplace is true', () => {
const MockClass = cls(TestClass, {inplace: true});
expect((MockClass as ClsMock<typeof TestClass>).__is_mocked__).toBe(true);

@@ -466,4 +611,4 @@ });

it('should mark mock class with IS_MOCKED symbol when inPlace is true', () => {
const MockClass = cls(TestClass, {inPlace: true});
it('should mark mock class with IS_MOCKED symbol when inplace is true', () => {
const MockClass = cls(TestClass, {inplace: true});
expect((MockClass as ClsMock<typeof TestClass>).__is_mocked__).toBe(true);

@@ -470,0 +615,0 @@ });

@@ -73,5 +73,5 @@ import {IS_MOCKED} from '../../constants/mock-symbols';

it('should modify original when inPlace is true', () => {
it('should modify original when inplace is true', () => {
const _original = new TestClass('test');
const mock = obj(_original, {inPlace: true});
const mock = obj(_original, {inplace: true});
expect(mock).toBe(_original);

@@ -82,3 +82,3 @@ });

const _original = new TestClass('test');
const mock = obj(_original, {inPlace: false, prototypeChain: false});
const mock = obj(_original, {inplace: false, prototypeChain: false});
mock.increment();

@@ -118,5 +118,5 @@ expect(_original.getCounter()).toBe(0); // Original should be unchanged

it('should support super calls and modify original when inPlace is true', () => {
it('should support super calls and modify original when inplace is true', () => {
const child = new Child();
const mock = obj(child, {inPlace: true});
const mock = obj(child, {inplace: true});
expect(mock.getValue()).toBe('child:parent');

@@ -127,5 +127,5 @@ expect(mock.childMethod()).toBe('child:base');

it('should support super calls and create new instance when inPlace is false', () => {
it('should support super calls and create new instance when inplace is false', () => {
const child = new Child();
const mock = obj(child, {inPlace: false});
const mock = obj(child, {inplace: false});
expect(mock.getValue()).toBe('child:parent');

@@ -298,5 +298,5 @@ expect(mock.childMethod()).toBe('child:base');

it('should handle class mock with inPlace', () => {
it('should handle class mock with inplace', () => {
const _original = new TestClass();
const MockTestClass = cls(TestClass, {inPlace: true});
const MockTestClass = cls(TestClass, {inplace: true});
const instance = new MockTestClass();

@@ -322,2 +322,67 @@ const objectMock = obj(instance);

});
describe('pattern matching', () => {
class TestService {
getValue() {
return 'value';
}
setValue(value: string) {
return value;
}
protected _internalMethod() {
return 'internal';
}
getValueAsync() {
return Promise.resolve('async value');
}
callInternalMethod() {
return this._internalMethod();
}
}
it('should mock methods matching patterns', () => {
const service = new TestService();
const mock = obj(service, {
patterns: ['get*'],
prototypeChain: true,
});
expect(mock.getValue).toHaveProperty('mock');
expect(mock.getValueAsync).toHaveProperty('mock');
expect(typeof mock.setValue).toBe('function');
expect(mock.setValue('test')).toBe('test');
});
it('should exclude methods matching negative patterns', () => {
const service = new TestService();
const mock = obj(service, {
patterns: ['*', '!set*', '!_*'],
prototypeChain: true,
});
expect(mock.getValue).toHaveProperty('mock');
expect(mock.getValueAsync).toHaveProperty('mock');
expect(typeof mock.setValue).toBe('function');
expect(mock.setValue('test')).toBe('test');
expect(mock.callInternalMethod()).toBe('internal');
});
it('should support complex pattern combinations', () => {
const service = new TestService();
const mock = obj(service, {
patterns: ['get*', '!_*'],
prototypeChain: true,
});
expect(mock.getValue).toHaveProperty('mock');
expect(mock.getValueAsync).toHaveProperty('mock');
expect(typeof mock.setValue).toBe('function');
expect(mock.setValue('test')).toBe('test');
expect(mock.callInternalMethod()).toBe('internal');
});
});
});

@@ -1,43 +0,13 @@

import {IS_MOCKED, MOCK_SYMBOLS} from '../constants/mock-symbols';
import {IS_MOCKED} from '../constants/mock-symbols';
import {DEFAULT_CLASS_OPTIONS} from '../defaults';
import {createSpy} from '../spy';
import {ClassMockOptions, ClsMock, Constructor} from '../types';
import {createDebugContext} from '../utils/debug';
import {createMockConstructor, setupMockClassPrototype} from '../utils/mock-constructor';
import {mockMethods} from '../utils/mock-descriptors';
import {handleStaticMethodInheritance} from '../utils/mock-method-filters';
import {markAsMocked} from '../utils/mock-state';
function handleStaticMethodInheritance(
mockClass: any,
originalClass: any,
_options: Partial<ClassMockOptions> = {},
): void {
let currentProto = Object.getPrototypeOf(originalClass);
while (currentProto && currentProto !== Function.prototype) {
Object.getOwnPropertyNames(currentProto)
.filter(prop => typeof currentProto[prop] === 'function')
.forEach(methodName => {
if (!mockClass[methodName]) {
const method = currentProto[methodName].bind(mockClass);
mockClass[methodName] = createSpy(method);
}
});
currentProto = Object.getPrototypeOf(currentProto);
}
}
function initializeMockInstance(instance: any, config: ClassMockOptions): void {
// Use symbols for all mock-related properties
instance[MOCK_SYMBOLS.STATES] = new Map();
instance[MOCK_SYMBOLS.STATE_KEY] = Symbol('state');
instance[MOCK_SYMBOLS.INSTANCE_ID] = Symbol('instance');
instance[MOCK_SYMBOLS.CONFIG] = config;
if (config.debug) {
instance[MOCK_SYMBOLS.DEBUG_CONTEXT] = createDebugContext(config);
}
}
/**
* Creates a mock class with all methods and properties mocked while preserving the original class structure.
* By default, it returns a new mock class.
* Can optionally modify the original class if inPlace option is set to true.
* Can optionally modify the original class if inplace option is set to true.
*

@@ -74,2 +44,4 @@ * Key features:

...DEFAULT_CLASS_OPTIONS,
// When inplace is true, enable static method mocking by default
static: options.inplace ? true : DEFAULT_CLASS_OPTIONS.static,
...options,

@@ -82,78 +54,17 @@ };

if (config.inPlace) {
// Modify the original class (when inPlace is true)
// Mark the class as mocked
Object.defineProperties(target, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});
if (config.inplace) {
// Modify the original class (when inplace is true)
markAsMocked(target);
markAsMocked(target.prototype);
// Mock prototype methods
Object.getOwnPropertyNames(target.prototype).forEach(prop => {
if (prop === 'constructor') return;
const descriptor = Object.getOwnPropertyDescriptor(target.prototype, prop);
if (descriptor) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(target.prototype, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(target.prototype, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value) : createSpy(),
});
}
}
});
mockMethods(target.prototype, target.prototype, config, config.patterns);
// Mark prototype as mocked
Object.defineProperties(target.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});
// Mock static methods
Object.getOwnPropertyNames(target).forEach(prop => {
if (prop === 'length' || prop === 'prototype' || prop === 'name') return;
const descriptor = Object.getOwnPropertyDescriptor(target, prop);
if (descriptor) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(target, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(target, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value) : createSpy(),
});
}
}
});
if (config.static !== false) {
mockMethods(target, target, config, Array.isArray(config.static) ? config.static : undefined);
}
// Handle static methods inheritance
handleStaticMethodInheritance(target, target, {debug: config.debug});
// Handle static methods inheritance with updated config
handleStaticMethodInheritance(target, target, config);

@@ -164,128 +75,19 @@ return target as unknown as ClsMock<T>;

// Create a new mock class (default behavior)
const MockClass = function (this: any, ...args: any[]) {
// Handle constructor call without new
if (!(this instanceof MockClass)) {
return new (MockClass as any)(...args);
}
const MockClass = createMockConstructor(target, config);
// Create instance with proper prototype
const instance = Object.create(target.prototype);
Object.setPrototypeOf(instance, MockClass.prototype);
// Set up prototype chain and mark as mocked
setupMockClassPrototype(MockClass, target);
// Initialize mock properties using symbols
initializeMockInstance(instance, config);
// Mark instance as mocked
Object.defineProperties(instance, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});
// Call original constructor if preserving constructor
if (config.preserveConstructor) {
const constructedInstance = Reflect.construct(target, args);
// Copy instance properties
Object.getOwnPropertyNames(constructedInstance).forEach(prop => {
if (!(prop in instance)) {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
Object.defineProperty(instance, prop, descriptor);
}
}
});
}
return instance;
};
// Set up prototype chain
Object.setPrototypeOf(MockClass, target);
Object.setPrototypeOf(MockClass.prototype, target.prototype);
// Mark mock class as mocked
Object.defineProperties(MockClass, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});
// Mark mock class prototype as mocked
Object.defineProperties(MockClass.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});
// Mock prototype methods
Object.getOwnPropertyNames(target.prototype).forEach(prop => {
if (prop === 'constructor') return;
const descriptor = Object.getOwnPropertyDescriptor(target.prototype, prop);
if (descriptor) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(MockClass.prototype, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(MockClass.prototype, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value) : createSpy(),
});
}
}
});
mockMethods(MockClass.prototype, target.prototype, config, config.patterns);
// Mock static methods
Object.getOwnPropertyNames(target).forEach(prop => {
if (prop === 'length' || prop === 'prototype' || prop === 'name') return;
const descriptor = Object.getOwnPropertyDescriptor(target, prop);
if (descriptor) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(MockClass, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(MockClass, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value) : createSpy(),
});
}
}
});
if (config.static !== false) {
mockMethods(MockClass, target, config, Array.isArray(config.static) ? config.static : undefined);
}
// Handle static methods inheritance
handleStaticMethodInheritance(MockClass, target, {debug: config.debug});
// Handle static methods inheritance with updated config
handleStaticMethodInheritance(MockClass, target, config);
return MockClass as unknown as ClsMock<T>;
}

@@ -1,51 +0,32 @@

import rfdc from 'rfdc';
import {IS_MOCKED} from '../constants/mock-symbols';
import {createSpy} from '../spy';
import {Fn, MockObject, ObjectMockOptions} from '../types';
import {cloneDeep, shallowClone} from '../utils/clone';
import {isMocked} from '../utils/mock-handlers';
import {createMethodSpy, mockObjectMethods} from '../utils/mock-methods';
const clone = rfdc({circles: true, proto: true});
/**
* Creates a shallow clone of an object while preserving its prototype chain
*/
function shallowClone<T extends object>(obj: T): T {
const clone = Object.create(Object.getPrototypeOf(obj));
Object.getOwnPropertyNames(obj).forEach(key => {
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor) {
Object.defineProperty(clone, key, descriptor);
}
});
return clone;
}
/**
* Creates a spy for a method while preserving its this binding
*/
function createMethodSpy<T extends object>(method: Fn, mockTarget: T, isArrowFn: boolean): MockObject<Fn> {
const spy = createSpy();
const boundMethod = function (this: T, ...args: unknown[]) {
return method.apply(isArrowFn ? mockTarget : this, args);
};
spy.mockImplementation(boundMethod);
return spy;
}
/**
* Creates a mock object by replacing methods with spies and tracking properties.
* Can either modify the original object or create a clone.
* - Can modify the original object or create a clone
* - Supports method pattern matching for selective mocking
* - Handles prototype chain methods if enabled
* - Allows method and property overrides
* - Preserves non-method properties
* - Prevents re-mocking of already mocked objects
*
* @template T - The object type to mock
* @template T - The type of object to mock
* @param target - The object to mock
* @param options - Mock options including configuration
* @returns A mock object that tracks interactions
* @param options - Configuration options
* @param options.inplace - Whether to modify the target object or create a clone
* @param options.prototypeChain - Whether to mock methods from the prototype chain
* @param options.patterns - Glob patterns for selecting which methods to mock
* @param options.overrides - Object containing method and property overrides
* @returns The mocked object
* @throws {Error} If target is undefined
*/
export function obj<T extends object>(target: T | undefined, options: ObjectMockOptions<T> = {}): MockObject<T> {
if (!target) {
return {} as MockObject<T>;
throw new Error('Cannot mock undefined object');
}
// Check if the object is already mocked
// Return existing mock if already mocked
if (isMocked(target)) {

@@ -55,59 +36,17 @@ return target as MockObject<T>;

// Check if the object is a class instance that has been mocked
if ((target as any).constructor && (target as any).constructor[IS_MOCKED]) {
return target as MockObject<T>;
}
// Create mock target
const mockTarget = options.inplace ? target : options.prototypeChain ? cloneDeep(target) : shallowClone(target);
let mockTarget: T;
if (options.inPlace) {
mockTarget = target;
} else {
mockTarget = options.prototypeChain ? clone(target) : shallowClone(target);
}
// Mark the object as mocked
// Mark as mocked
Object.defineProperty(mockTarget, IS_MOCKED, {
value: true,
writable: false,
enumerable: false,
configurable: false,
writable: false,
});
// Process instance methods and properties
Object.entries(Object.getOwnPropertyDescriptors(target)).forEach(([key, descriptor]) => {
if (typeof descriptor.value === 'function') {
const method = descriptor.value;
const isArrowFn = !method.prototype;
const spy = createMethodSpy(method, mockTarget, isArrowFn);
// Mock methods
mockObjectMethods(mockTarget, target, options);
Object.defineProperty(mockTarget, key, {
...descriptor,
value: spy,
});
}
});
// Mock prototype chain methods if doing deep mocking
if (options.prototypeChain) {
let proto = Object.getPrototypeOf(target);
while (proto && proto !== Object.prototype) {
Object.entries(Object.getOwnPropertyDescriptors(proto)).forEach(([key, descriptor]) => {
// Only mock methods that haven't been mocked yet
if (!Object.prototype.hasOwnProperty.call(mockTarget, key) && typeof descriptor.value === 'function') {
const method = descriptor.value;
const isArrowFn = !method.prototype;
const spy = createMethodSpy(method, mockTarget, isArrowFn);
Object.defineProperty(mockTarget, key, {
...descriptor,
value: spy,
});
}
});
proto = Object.getPrototypeOf(proto);
}
}
// Apply overrides if provided
// Apply overrides
if (options.overrides) {

@@ -117,4 +56,3 @@ Object.entries(options.overrides).forEach(([key, value]) => {

if (typeof value === 'function') {
const spy = createSpy();
spy.mockImplementation(value as Fn);
const spy = createMethodSpy(value as Fn, mockTarget, !value.prototype);
mockTarget[propertyKey] = spy as T[keyof T];

@@ -121,0 +59,0 @@ } else {

@@ -8,2 +8,3 @@ import {Fn, MockFunction} from './types';

* such as call tracking, return value manipulation, and behavior verification.
* It supports both Jest and Jasmine style mocking APIs.
*

@@ -180,6 +181,21 @@ * @template T - The type of function being spied on

public getSpy(): MockFunction<T> {
/**
* Gets the spy function with all mock properties and methods attached.
* The returned spy function includes:
* - mock property for tracking calls, results, instances and contexts
* - Jest-style methods (mockReturnValue, mockImplementation, etc.)
* - Jasmine-style methods (and.returnValue, and.callFake, etc.)
* - Common assertions (toHaveBeenCalled, toHaveBeenCalledWith, etc.)
*/
getSpy(): MockFunction<T> {
return this.spyFunction;
}
/**
* Updates the spy's state by setting implementation, return value, or error.
* When updating one state, it clears other conflicting states to maintain consistency.
* For example, setting a return value will clear the implementation.
*
* @param updates - Object containing state updates
*/
private updateState(updates: {implementation?: T; returnValue?: ReturnType<T>; error?: any}): void {

@@ -213,4 +229,7 @@ // Reset all states

* Creates a new spy function with optional implementation.
* The spy includes both Jest and Jasmine style mocking APIs.
*
* @template T - The type of function to spy on
* @param implementation - Optional implementation for the spy
* @returns A spy function with mock tracking capabilities
*/

@@ -224,3 +243,6 @@ export function createSpy<T extends Fn>(implementation?: T): MockFunction<T> {

* Creates a spy for a property with getter and/or setter.
* Both the getter and setter are spies with full mock tracking capabilities.
*
* @template T - The type of the property
* @returns An object containing spy functions for get and set operations
*/

@@ -227,0 +249,0 @@ export function createPropertySpy<T>(): {

@@ -115,3 +115,3 @@ import {IS_MOCKED} from '../constants/mock-symbols';

*/
inPlace?: boolean;
inplace?: boolean;

@@ -154,6 +154,17 @@ /**

* When false, only mocks the top level object's own methods
* Only applies when inPlace is false
* Only applies when inplace is false
* @default false
*/
prototypeChain?: boolean;
/**
* Glob patterns for methods/properties to mock
* Supports ! prefix for exclusion
* Examples:
* - ['get*'] - mock all methods starting with 'get'
* - ['!private*'] - exclude all methods starting with 'private'
* - ['handle{Get,Post}*'] - mock all methods starting with handleGet or handlePost
* @default undefined - mocks everything except constructor
*/
patterns?: string[];
}

@@ -181,7 +192,26 @@

/**
* Controls whether to mock static class members
* Includes static methods, properties, and getters/setters
* Glob patterns for methods/properties to mock
* Supports ! prefix for exclusion
* Examples:
* - ['get*'] - mock all methods starting with 'get'
* - ['!private*'] - exclude all methods starting with 'private'
* - ['handle{Get,Post}*'] - mock all methods starting with handleGet or handlePost
* @default undefined - mocks everything except constructor
*/
patterns?: string[];
/**
* Controls static member mocking
* Can be boolean to mock all/none static members
* Or array of glob patterns with ! prefix for exclusion
* @default false
*/
static?: boolean;
static?: boolean | string[];
/**
* Controls whether to mock inherited methods
* When false, only mocks methods defined directly on the class
* @default true
*/
inheritance?: boolean;
}

@@ -417,7 +447,2 @@

/**
* Creates a factory-based mock class that automatically mocks instances on construction
*/
factory<T extends Constructor<any>>(target: T, options?: ObjectMockOptions): T;
/**
* Casts a partial implementation to a complete mock

@@ -424,0 +449,0 @@ */

@@ -64,3 +64,3 @@ import {IS_MOCKED} from '../../constants/mock-symbols';

it('should handle class mock with inPlace', () => {
it('should handle class mock with inplace', () => {
class TestClass {

@@ -71,3 +71,3 @@ method() {

}
const MockTestClass = cls(TestClass, {inPlace: true});
const MockTestClass = cls(TestClass, {inplace: true});
expect(isMocked(MockTestClass)).toBe(true);

@@ -74,0 +74,0 @@

@@ -25,2 +25,4 @@ import {BaseMockOptions} from '../types';

export type MockType = 'object' | 'function' | 'class';
/**

@@ -95,3 +97,3 @@ * Debug context for mock operations

*/
logMockCreation(type: 'function' | 'object' | 'class'): void {
logMockCreation(type: MockType): void {
this.log(`Created new ${type} mock`, DebugLevel.INFO);

@@ -98,0 +100,0 @@ }

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc