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.7.0 to 0.8.0

src/mocks/__tests__/factory.spec.ts

8

dist/cjs/index.d.ts

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

*/
mockInPlace?: boolean;
inPlace?: boolean;
/**

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

* When false, only mocks the top level object's own methods
* Only applies when mockInPlace is false
* Only applies when inPlace is false
* @default false
*/
mockDeep?: boolean;
prototypeChain?: boolean;
}

@@ -183,3 +183,3 @@ /**

*/
mockStatic?: boolean;
static?: boolean;
}

@@ -186,0 +186,0 @@ /**

@@ -21,4 +21,4 @@ 'use strict';

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
mockDeep: true,
inPlace: false,
prototypeChain: true,
overrides: {}

@@ -28,6 +28,6 @@ };

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
inPlace: false,
preservePrototype: true,
preserveConstructor: true,
mockStatic: false,
static: false,
overrides: {}

@@ -777,5 +777,17 @@ };

}
if (config.mockInPlace) {
target[IS_MOCKED] = true;
target.__is_mocked__ = true;
if (config.inPlace) {
Object.defineProperties(target, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.getOwnPropertyNames(target.prototype).forEach((prop) => {

@@ -799,2 +811,16 @@ if (prop === "constructor") return;

});
Object.defineProperties(target.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.getOwnPropertyNames(target).forEach((prop) => {

@@ -828,13 +854,22 @@ if (prop === "length" || prop === "prototype" || prop === "name") return;

initializeMockInstance(instance, config);
Object.defineProperties(instance, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
if (config.preserveConstructor) {
const constructedInstance = Reflect.construct(target, args);
Object.getOwnPropertyNames(constructedInstance).forEach((prop) => {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(descriptor.value.bind(instance))
});
} else {
if (!(prop in instance)) {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
Object.defineProperty(instance, prop, descriptor);

@@ -845,46 +880,52 @@ }

}
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(instance, prop, {
...descriptor,
value: createSpy(override)
});
} else if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy()
});
}
}
});
let proto = Object.getPrototypeOf(target.prototype);
while (proto && proto !== Object.prototype) {
Object.getOwnPropertyNames(proto).forEach((prop) => {
if (prop === "constructor") return;
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
if (descriptor && !instance.hasOwnProperty(prop)) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(override)
});
} else if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy()
});
}
}
});
proto = Object.getPrototypeOf(proto);
}
return instance;
};
MockClass.prototype = Object.create(target.prototype);
Object.setPrototypeOf(MockClass, target);
Object.setPrototypeOf(MockClass.prototype, target.prototype);
Object.defineProperties(MockClass, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.defineProperties(MockClass.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
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()
});
}
}
});
Object.getOwnPropertyNames(target).forEach((prop) => {

@@ -909,4 +950,2 @@ if (prop === "length" || prop === "prototype" || prop === "name") return;

handleStaticMethodInheritance(MockClass, target, { debug: config.debug });
MockClass[IS_MOCKED] = true;
MockClass.__is_mocked__ = true;
return MockClass;

@@ -945,3 +984,39 @@ }

function isMocked(target) {
return target && typeof target === "object" && "mockClear" in target && "mockReset" in target && "mockRestore" in target;
if (!target) {
return false;
}
if (typeof target === "function") {
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
if (target.prototype && (Object.prototype.hasOwnProperty.call(target.prototype, IS_MOCKED) || IS_MOCKED in target.prototype)) {
return true;
}
if ("mockClear" in target && "mockReset" in target && "mockRestore" in target) {
return true;
}
return false;
}
if (typeof target === "object") {
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
const proto = Object.getPrototypeOf(target);
if (proto) {
let currentProto = proto;
while (currentProto && currentProto !== Object.prototype) {
if (Object.prototype.hasOwnProperty.call(currentProto, IS_MOCKED) || IS_MOCKED in currentProto) {
return true;
}
if (currentProto.constructor && (Object.prototype.hasOwnProperty.call(currentProto.constructor, IS_MOCKED) || IS_MOCKED in currentProto.constructor)) {
return true;
}
currentProto = Object.getPrototypeOf(currentProto);
}
}
if ("mockClear" in target && "mockReset" in target && "mockRestore" in target) {
return true;
}
}
return false;
}

@@ -976,8 +1051,17 @@

}
if (target.constructor && target.constructor[IS_MOCKED]) {
return target;
}
let mockTarget;
if (options.mockInPlace) {
if (options.inPlace) {
mockTarget = target;
} else {
mockTarget = options.mockDeep ? clone(target) : shallowClone(target);
mockTarget = options.prototypeChain ? clone(target) : shallowClone(target);
}
Object.defineProperty(mockTarget, IS_MOCKED, {
value: true,
enumerable: false,
configurable: false,
writable: false
});
Object.entries(Object.getOwnPropertyDescriptors(target)).forEach(([key, descriptor]) => {

@@ -994,3 +1078,3 @@ if (typeof descriptor.value === "function") {

});
if (options.mockDeep) {
if (options.prototypeChain) {
let proto = Object.getPrototypeOf(target);

@@ -997,0 +1081,0 @@ while (proto && proto !== Object.prototype) {

@@ -15,4 +15,4 @@ import rfdc from 'rfdc';

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
mockDeep: true,
inPlace: false,
prototypeChain: true,
overrides: {}

@@ -22,6 +22,6 @@ };

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
inPlace: false,
preservePrototype: true,
preserveConstructor: true,
mockStatic: false,
static: false,
overrides: {}

@@ -771,5 +771,17 @@ };

}
if (config.mockInPlace) {
target[IS_MOCKED] = true;
target.__is_mocked__ = true;
if (config.inPlace) {
Object.defineProperties(target, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.getOwnPropertyNames(target.prototype).forEach((prop) => {

@@ -793,2 +805,16 @@ if (prop === "constructor") return;

});
Object.defineProperties(target.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.getOwnPropertyNames(target).forEach((prop) => {

@@ -822,13 +848,22 @@ if (prop === "length" || prop === "prototype" || prop === "name") return;

initializeMockInstance(instance, config);
Object.defineProperties(instance, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
if (config.preserveConstructor) {
const constructedInstance = Reflect.construct(target, args);
Object.getOwnPropertyNames(constructedInstance).forEach((prop) => {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(descriptor.value.bind(instance))
});
} else {
if (!(prop in instance)) {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
Object.defineProperty(instance, prop, descriptor);

@@ -839,46 +874,52 @@ }

}
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(instance, prop, {
...descriptor,
value: createSpy(override)
});
} else if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy()
});
}
}
});
let proto = Object.getPrototypeOf(target.prototype);
while (proto && proto !== Object.prototype) {
Object.getOwnPropertyNames(proto).forEach((prop) => {
if (prop === "constructor") return;
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
if (descriptor && !instance.hasOwnProperty(prop)) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(override)
});
} else if (typeof descriptor.value === "function") {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy()
});
}
}
});
proto = Object.getPrototypeOf(proto);
}
return instance;
};
MockClass.prototype = Object.create(target.prototype);
Object.setPrototypeOf(MockClass, target);
Object.setPrototypeOf(MockClass.prototype, target.prototype);
Object.defineProperties(MockClass, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
Object.defineProperties(MockClass.prototype, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false
}
});
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()
});
}
}
});
Object.getOwnPropertyNames(target).forEach((prop) => {

@@ -903,4 +944,2 @@ if (prop === "length" || prop === "prototype" || prop === "name") return;

handleStaticMethodInheritance(MockClass, target, { debug: config.debug });
MockClass[IS_MOCKED] = true;
MockClass.__is_mocked__ = true;
return MockClass;

@@ -939,3 +978,39 @@ }

function isMocked(target) {
return target && typeof target === "object" && "mockClear" in target && "mockReset" in target && "mockRestore" in target;
if (!target) {
return false;
}
if (typeof target === "function") {
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
if (target.prototype && (Object.prototype.hasOwnProperty.call(target.prototype, IS_MOCKED) || IS_MOCKED in target.prototype)) {
return true;
}
if ("mockClear" in target && "mockReset" in target && "mockRestore" in target) {
return true;
}
return false;
}
if (typeof target === "object") {
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
const proto = Object.getPrototypeOf(target);
if (proto) {
let currentProto = proto;
while (currentProto && currentProto !== Object.prototype) {
if (Object.prototype.hasOwnProperty.call(currentProto, IS_MOCKED) || IS_MOCKED in currentProto) {
return true;
}
if (currentProto.constructor && (Object.prototype.hasOwnProperty.call(currentProto.constructor, IS_MOCKED) || IS_MOCKED in currentProto.constructor)) {
return true;
}
currentProto = Object.getPrototypeOf(currentProto);
}
}
if ("mockClear" in target && "mockReset" in target && "mockRestore" in target) {
return true;
}
}
return false;
}

@@ -970,8 +1045,17 @@

}
if (target.constructor && target.constructor[IS_MOCKED]) {
return target;
}
let mockTarget;
if (options.mockInPlace) {
if (options.inPlace) {
mockTarget = target;
} else {
mockTarget = options.mockDeep ? clone(target) : shallowClone(target);
mockTarget = options.prototypeChain ? clone(target) : shallowClone(target);
}
Object.defineProperty(mockTarget, IS_MOCKED, {
value: true,
enumerable: false,
configurable: false,
writable: false
});
Object.entries(Object.getOwnPropertyDescriptors(target)).forEach(([key, descriptor]) => {

@@ -988,3 +1072,3 @@ if (typeof descriptor.value === "function") {

});
if (options.mockDeep) {
if (options.prototypeChain) {
let proto = Object.getPrototypeOf(target);

@@ -991,0 +1075,0 @@ while (proto && proto !== Object.prototype) {

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

@@ -5,0 +5,0 @@ "keywords": [

@@ -150,2 +150,34 @@ # @corez/mock

#### Advanced Object Mocking Features
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

@@ -167,5 +199,4 @@

const MockDatabase = mock.cls(Database, {
overrides: {
query: async () => [{id: 1}],
},
static: true,
preserveConstructor: true,
});

@@ -184,3 +215,3 @@

mock.cls(Database, {
mockInPlace: true,
inPlace: true,
overrides: {

@@ -245,34 +276,27 @@ query: async () => [{id: 1}],

#### `mock.obj<T extends object>(target: T | undefined, options?: ObjMockOptions<T>): MockObject<T>`
#### `mock.obj<T extends object>(target: T | undefined, options?: ObjectMockOptions<T>): MockObject<T>`
Creates a mock object with automatic method tracking:
Creates a mock object with automatic method tracking. Available options:
```typescript
interface UserService {
getUser(id: number): Promise<User>;
updateUser(user: User): Promise<void>;
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>;
}
```
const userService = mock.obj<UserService>(
{
getUser: async id => ({id, name: 'John'}),
updateUser: async user => {},
},
{
overrides: {
getUser: async id => ({id, name: 'Mock User'}),
},
},
);
Key features:
// Access call information
const getUserMock = userService.getUser as MockFunction;
console.log(getUserMock.calls.count());
console.log(getUserMock.calls.all());
- 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
// Verify specific calls
expect(getUserMock.calls.count()).toBe(1);
expect(getUserMock.calls.all()[0].args).toEqual([1]);
```
#### `mock.cls<T extends Constructor<any>>(target: T, options?: ClassMockOptions<T>): ClsMock<T>`

@@ -286,3 +310,3 @@

// Modify original class instead of creating new one
mockInPlace: false,
inPlace: false,

@@ -320,3 +344,3 @@ // Preserve original method implementations

// Whether to modify the original class
mockInPlace?: boolean;
inPlace?: boolean;

@@ -569,8 +593,8 @@ // Whether to preserve original method implementations

5. **Using mockInPlace**
5. **Using inPlace**
```typescript
// For objects: Use mockInPlace when you need to maintain object references
// For objects: Use inPlace when you need to maintain object references
const mockObj = mock.obj(original, {
mockInPlace: true,
inPlace: true,
overrides: {

@@ -581,3 +605,3 @@ method: () => 'mocked',

// For classes: Be cautious with mockInPlace as it affects the original class
// For classes: Be cautious with inPlace as it affects the original class
const MockClass = mock.cls(Original); // Creates new class by default

@@ -587,3 +611,3 @@

const ModifiedClass = mock.cls(Original, {
mockInPlace: true,
inPlace: true,
// Remember to restore if needed

@@ -612,15 +636,15 @@ });

- For classes: Use `preservePrototype: true` (default)
- For objects: Use `mockDeep: true` to mock prototype methods (default)
- For objects: Use `prototypeChain: true` to mock prototype methods (default)
- For type casting: Use `keepPrototype: true` (default)
4. **mockInPlace Issues**
- For objects: Use `mockInPlace: true` if you need to maintain object references
- For classes: Be aware that `mockInPlace: true` modifies the original class
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, {mockInPlace: true});
const mock = mock.obj(original, {inPlace: true});
// ... use mock ...
mock.restore(); // Restore original implementation
```
- When using `mockInPlace` with inheritance, ensure proper super calls are preserved
- 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

@@ -656,8 +680,8 @@

- `mockInPlace`: Controls whether to modify the original object or create a new one (default: false)
- `mockDeep`: Controls whether to perform deep cloning and mocking of nested objects and prototype chain methods
- `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 mockInPlace:
Example of object mocking with inPlace:

@@ -674,3 +698,3 @@ ```typescript

const modifiedObj = mock.obj(original, {
mockInPlace: true,
inPlace: true,
overrides: {

@@ -683,3 +707,3 @@ method: () => 'mocked',

const deepMockObj = mock.obj(original, {
mockDeep: true, // this is default
prototypeChain: true, // this is default
});

@@ -692,3 +716,3 @@ ```

- `mockInPlace`: Controls whether to modify the original class or create a new one (default: false)
- `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)

@@ -699,3 +723,3 @@ - `preserveConstructor`: Controls whether to preserve the original constructor behavior (default: true)

Example of class mocking with mockInPlace:
Example of class mocking with inPlace:

@@ -705,3 +729,3 @@ ```typescript

const MockClass = mock.cls(Original, {
mockStatic: true,
static: true,
overrides: {

@@ -714,4 +738,4 @@ method: () => 'mocked',

const ModifiedClass = mock.cls(Original, {
mockInPlace: true,
mockStatic: true,
inPlace: true,
static: true,
overrides: {

@@ -718,0 +742,0 @@ method: () => 'mocked',

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

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
mockDeep: true,
inPlace: false,
prototypeChain: true,
overrides: {},

@@ -40,6 +40,6 @@ };

...DEFAULT_BASE_OPTIONS,
mockInPlace: false,
inPlace: false,
preservePrototype: true,
preserveConstructor: true,
mockStatic: false,
static: false,
overrides: {},

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

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

const MockedClass = cls(CallbackURL, {mockInPlace: 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 mockInPlace is true', () => {
it('should handle inheritance correctly when inPlace is true', () => {
class ExtendedChild extends Base {

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

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

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

it('should handle static inheritance when mockInPlace 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, {mockInPlace: true});
const MockStaticChild = cls(StaticChild, {inPlace: true, static: true});

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

it('should handle super calls correctly when mockInPlace 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, {mockInPlace: true});
const MockChild = cls(SuperChild, {inPlace: true});
const instance = new MockChild('test');

@@ -410,3 +410,3 @@

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

@@ -422,24 +422,5 @@ value: string = 'original';

it('should create new mock class and keep original unchanged by default', () => {
const MockClass = cls(TestClass);
it('should modify original class when inPlace is true', () => {
const ModifiedClass = cls(TestClass, {inPlace: true});
// Verify MockClass is a different class
expect(MockClass).not.toBe(TestClass);
// Verify MockClass has mock methods
const mockInstance = new MockClass();
expect(mockInstance.getValue).toHaveProperty('mock');
expect(MockClass.staticMethod).toHaveProperty('mock');
// Verify original class remains unchanged
const originalInstance = new TestClass();
expect(originalInstance.getValue).not.toHaveProperty('mock');
expect(TestClass.staticMethod).not.toHaveProperty('mock');
expect(originalInstance.getValue()).toBe('original');
expect(TestClass.staticMethod()).toBe('static');
});
it('should modify original class when mockInPlace is true', () => {
const ModifiedClass = cls(TestClass, {mockInPlace: true});
// Verify returned class is the same as original

@@ -464,35 +445,5 @@ expect(ModifiedClass).toBe(TestClass);

it('should allow restoring original class after modification', () => {
class LocalTestClass {
value: string = 'original';
getValue(): string {
return this.value;
}
static staticMethod(): string {
return 'static';
}
}
// Store original methods
const originalGetValue = LocalTestClass.prototype.getValue;
const originalStaticMethod = LocalTestClass.staticMethod;
// Modify class
const ModifiedClass = cls(LocalTestClass, {mockInPlace: true});
// Verify class is modified
const modifiedInstance = new ModifiedClass();
expect(modifiedInstance.getValue).toHaveProperty('mock');
expect(ModifiedClass.staticMethod).toHaveProperty('mock');
// Restore original methods
LocalTestClass.prototype.getValue = originalGetValue;
LocalTestClass.staticMethod = originalStaticMethod;
// Verify class is restored
const restoredInstance = new LocalTestClass();
expect(restoredInstance.getValue).not.toHaveProperty('mock');
expect(LocalTestClass.staticMethod).not.toHaveProperty('mock');
expect(restoredInstance.getValue()).toBe('original');
expect(LocalTestClass.staticMethod()).toBe('static');
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);
});

@@ -514,4 +465,4 @@ });

it('should mark mock class with IS_MOCKED symbol when mockInPlace is true', () => {
const MockClass = cls(TestClass, {mockInPlace: 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);

@@ -518,0 +469,0 @@ });

@@ -0,2 +1,6 @@

import {IS_MOCKED} from '../../constants/mock-symbols';
import {MockFunction} from '../../types';
import {isMocked} from '../../utils/mock-handlers';
import {obj} from '..';
import {cls} from '../class';

@@ -64,18 +68,18 @@ describe('object', () => {

it('should create new instance by default', () => {
const original = new TestClass('test');
const mock = obj(original);
expect(mock).not.toBe(original);
const _original = new TestClass('test');
const mock = obj(_original);
expect(mock).not.toBe(_original);
});
it('should modify original when mockInPlace is true', () => {
const original = new TestClass('test');
const mock = obj(original, {mockInPlace: true});
expect(mock).toBe(original);
it('should modify original when inPlace is true', () => {
const _original = new TestClass('test');
const mock = obj(_original, {inPlace: true});
expect(mock).toBe(_original);
});
it('should create shallow clone when not mocking in place', () => {
const original = new TestClass('test');
const mock = obj(original, {mockInPlace: false, mockDeep: false});
const _original = new TestClass('test');
const mock = obj(_original, {inPlace: false, prototypeChain: false});
mock.increment();
expect(original.getCounter()).toBe(0); // Original should be unchanged
expect(_original.getCounter()).toBe(0); // Original should be unchanged
});

@@ -113,5 +117,5 @@

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

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

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

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

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

@@ -142,3 +146,3 @@ expect(mock.childMethod()).toBe('child:base');

it('should handle deep cloning', () => {
const original = {
const _original = {
nested: {

@@ -152,5 +156,5 @@ value: 123,

const mock = obj(original, {mockDeep: true});
expect(mock).not.toBe(original);
expect(mock.nested).not.toBe(original.nested);
const mock = obj(_original, {prototypeChain: true});
expect(mock).not.toBe(_original);
expect(mock.nested).not.toBe(_original.nested);
expect(mock.nested.value).toBe(123);

@@ -175,3 +179,3 @@ expect(mock.nested.method()).toBe(123);

const mock = obj(circular, {mockDeep: true});
const mock = obj(circular, {prototypeChain: true});
expect(mock).not.toBe(circular);

@@ -264,2 +268,58 @@ expect(mock.self).toBe(mock);

});
describe('mock detection', () => {
class TestClass {
value = 'test';
getValue() {
return this.value;
}
}
it('should mark mocked object with IS_MOCKED symbol', () => {
const testObj = {method: () => 'test'};
const mock = obj(testObj);
expect(IS_MOCKED in mock).toBe(true);
expect(isMocked(mock)).toBe(true);
});
it('should detect already mocked objects', () => {
const testObj = {method: () => 'test'};
const firstMock = obj(testObj);
const secondMock = obj(firstMock);
expect(secondMock).toBe(firstMock);
});
it('should detect class mocked instances', () => {
const MockTestClass = cls(TestClass);
const instance = new MockTestClass();
const objectMock = obj(instance);
// Should return the same instance without re-mocking
expect(objectMock).toBe(instance);
expect(isMocked(objectMock)).toBe(true);
});
it('should handle class mock with inPlace', () => {
const _original = new TestClass();
const MockTestClass = cls(TestClass, {inPlace: true});
const instance = new MockTestClass();
const objectMock = obj(instance);
// Should detect mocked class and return same instance
expect(objectMock).toBe(instance);
expect(isMocked(objectMock)).toBe(true);
});
it('should preserve mock functionality when detecting class mocked instances', () => {
const MockTestClass = cls(TestClass);
const instance = new MockTestClass();
// Mock a method on the class instance
(instance.getValue as MockFunction<() => string>).mockImplementation(() => 'mocked');
// Object mock should return same instance without affecting mocks
const objectMock = obj(instance);
expect(objectMock).toBe(instance);
});
});
});

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

* By default, it returns a new mock class.
* Can optionally modify the original class if mockInPlace option is set to true.
* Can optionally modify the original class if inPlace option is set to true.
*

@@ -82,7 +82,19 @@ * Key features:

if (config.mockInPlace) {
// Modify the original class (when mockInPlace is true)
if (config.inPlace) {
// Modify the original class (when inPlace is true)
// Mark the class as mocked
(target as any)[IS_MOCKED] = true;
(target as any).__is_mocked__ = true;
Object.defineProperties(target, {
[IS_MOCKED]: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
__is_mocked__: {
value: true,
enumerable: false,
configurable: false,
writable: false,
},
});

@@ -109,2 +121,18 @@ // Mock prototype methods

// 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

@@ -150,2 +178,18 @@ Object.getOwnPropertyNames(target).forEach(prop => {

// 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

@@ -156,10 +200,5 @@ if (config.preserveConstructor) {

Object.getOwnPropertyNames(constructedInstance).forEach(prop => {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
if (typeof descriptor.value === 'function') {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(descriptor.value.bind(instance)),
});
} else {
if (!(prop in instance)) {
const descriptor = Object.getOwnPropertyDescriptor(constructedInstance, prop);
if (descriptor) {
Object.defineProperty(instance, prop, descriptor);

@@ -171,46 +210,2 @@ }

// 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(instance, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy(),
});
}
}
});
// Handle inherited methods
let proto = Object.getPrototypeOf(target.prototype);
while (proto && proto !== Object.prototype) {
Object.getOwnPropertyNames(proto).forEach(prop => {
if (prop === 'constructor') return;
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
if (descriptor && !instance.hasOwnProperty(prop)) {
const override = config.overrides?.[prop];
if (override) {
Object.defineProperty(instance, prop, {
...descriptor,
value: createSpy(override),
});
} else if (typeof descriptor.value === 'function') {
Object.defineProperty(instance, prop, {
...descriptor,
value: config.preservePrototype ? createSpy(descriptor.value.bind(instance)) : createSpy(),
});
}
}
});
proto = Object.getPrototypeOf(proto);
}
return instance;

@@ -220,6 +215,58 @@ };

// Set up prototype chain
MockClass.prototype = Object.create(target.prototype);
Object.setPrototypeOf(MockClass, target);
Object.setPrototypeOf(MockClass.prototype, target.prototype);
// Copy static properties
// 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(),
});
}
}
});
// Mock static methods
Object.getOwnPropertyNames(target).forEach(prop => {

@@ -247,7 +294,3 @@ if (prop === 'length' || prop === 'prototype' || prop === 'name') return;

// Mark the mock class as mocked
(MockClass as any)[IS_MOCKED] = true;
(MockClass as any).__is_mocked__ = true;
return MockClass as unknown as ClsMock<T>;
}
import rfdc from 'rfdc';
import {IS_MOCKED} from '../constants/mock-symbols';
import {createSpy} from '../spy';

@@ -54,10 +55,23 @@ import {Fn, MockObject, ObjectMockOptions} from '../types';

// 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>;
}
let mockTarget: T;
if (options.mockInPlace) {
if (options.inPlace) {
mockTarget = target;
} else {
mockTarget = options.mockDeep ? clone(target) : shallowClone(target);
mockTarget = options.prototypeChain ? clone(target) : shallowClone(target);
}
// Mark the object as mocked
Object.defineProperty(mockTarget, IS_MOCKED, {
value: true,
enumerable: false,
configurable: false,
writable: false,
});
// Process instance methods and properties

@@ -78,3 +92,3 @@ Object.entries(Object.getOwnPropertyDescriptors(target)).forEach(([key, descriptor]) => {

// Mock prototype chain methods if doing deep mocking
if (options.mockDeep) {
if (options.prototypeChain) {
let proto = Object.getPrototypeOf(target);

@@ -81,0 +95,0 @@ while (proto && proto !== Object.prototype) {

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

*/
mockInPlace?: boolean;
inPlace?: boolean;

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

* When false, only mocks the top level object's own methods
* Only applies when mockInPlace is false
* Only applies when inPlace is false
* @default false
*/
mockDeep?: boolean;
prototypeChain?: boolean;
}

@@ -185,3 +185,3 @@

*/
mockStatic?: boolean;
static?: boolean;
}

@@ -188,0 +188,0 @@

@@ -0,8 +1,66 @@

import {IS_MOCKED} from '../constants/mock-symbols';
/**
* Check if an object is already mocked
* This checks both direct mock status and class mock status
*/
export function isMocked(target: any): boolean {
return (
target && typeof target === 'object' && 'mockClear' in target && 'mockReset' in target && 'mockRestore' in target
);
if (!target) {
return false;
}
// Check if target is a function (class constructor)
if (typeof target === 'function') {
// Check if class itself is mocked
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
// Check if class prototype is mocked
if (
target.prototype &&
(Object.prototype.hasOwnProperty.call(target.prototype, IS_MOCKED) || IS_MOCKED in target.prototype)
) {
return true;
}
// Check if class has mock methods
if ('mockClear' in target && 'mockReset' in target && 'mockRestore' in target) {
return true;
}
return false;
}
// Check if target is an object
if (typeof target === 'object') {
// Check if object itself is mocked
if (Object.prototype.hasOwnProperty.call(target, IS_MOCKED) || IS_MOCKED in target) {
return true;
}
// Check if object is an instance of a mocked class
const proto = Object.getPrototypeOf(target);
if (proto) {
// Check prototype chain for IS_MOCKED
let currentProto = proto;
while (currentProto && currentProto !== Object.prototype) {
if (Object.prototype.hasOwnProperty.call(currentProto, IS_MOCKED) || IS_MOCKED in currentProto) {
return true;
}
if (
currentProto.constructor &&
(Object.prototype.hasOwnProperty.call(currentProto.constructor, IS_MOCKED) ||
IS_MOCKED in currentProto.constructor)
) {
return true;
}
currentProto = Object.getPrototypeOf(currentProto);
}
}
// Check if object has mock methods
if ('mockClear' in target && 'mockReset' in target && 'mockRestore' in target) {
return true;
}
}
return false;
}

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 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