Skip to content

Commit

Permalink
fix: mock property support symbol (#62)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Enhanced mocking capabilities with support for Symbol and number
properties.
- Expanded test coverage for various asynchronous behaviors and error
handling scenarios.

- **Bug Fixes**
- Improved error handling in tests for file reading functions and HTTP
requests.

- **Documentation**
- Updated test descriptions to reflect new functionalities and broader
scope.

- **Refactor**
- Updated type annotations for property parameters to improve type
safety.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
fengmk2 authored Dec 21, 2024
1 parent 13a540c commit a7950f3
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 111 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"node": ">= 18.19.0"
},
"dependencies": {
"@cnpmjs/muk-prop": "^1.0.0",
"@cnpmjs/muk-prop": "^1.1.0",
"is-type-of": "^2.2.0",
"thenify": "^3.3.1"
},
Expand Down
87 changes: 0 additions & 87 deletions src/index.d.ts

This file was deleted.

34 changes: 17 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import is from 'is-type-of';
// @ts-ignore
import thenify from 'thenify';

function mock(target: any, property: string, value?: any) {
function mock(target: any, property: PropertyKey, value?: any) {
value = spyFunction(target, property, value);
return muk(target, property, value);
}

function spyFunction(target: any, property: string, fn: any) {
function spyFunction(target: any, property: PropertyKey, fn: any) {
if (!is.function(fn)) return fn;
// support mock with jest.fn()
if (fn._isMockFunction && fn.mock) return fn;
Expand All @@ -32,14 +32,14 @@ function spyFunction(target: any, property: string, fn: any) {
fn.called++;
const res = Reflect.apply(target, thisArg, args);
if (isAsyncLike && !is.promise(res)) {
throw new Error(`Can\'t mock async function to normal function for property "${property}"`);
throw new Error(`Can\'t mock async function to normal function for property "${String(property)}"`);
}
return res;
},
});
}

function isAsyncLikeFunction(target: any, property: string) {
function isAsyncLikeFunction(target: any, property: PropertyKey) {
// don't call getter
// Object.getOwnPropertyDescriptor can't find getter in prototypes
if (typeof target.__lookupGetter__ === 'function' && target.__lookupGetter__(property)) return false;
Expand Down Expand Up @@ -90,7 +90,7 @@ function _createError(error?: MockError, props?: Record<string, any>): Error {
return error;
}

function _mockError(mod: any, method: string, error?: MockError, props?: Record<string, any> | number,
function _mockError(mod: any, method: string | symbol, error?: MockError, props?: Record<string, any> | number,
timeout?: number | string, once?: boolean) {
if (typeof props === 'number') {
timeout = props;
Expand Down Expand Up @@ -140,7 +140,7 @@ function _mockError(mod: any, method: string, error?: MockError, props?: Record<
* @param {Object} props, error properties
* @param {Number} timeout, mock async callback timeout, default is 0.
*/
function mockError(mod: any, method: string, error?: MockError,
function mockError(mod: any, method: string | symbol, error?: MockError,
props?: Record<string, any> | number,
timeout?: number) {
return _mockError(mod, method, error, props, timeout);
Expand All @@ -154,7 +154,7 @@ function mockError(mod: any, method: string, error?: MockError,
* @param {Object} props, error properties
* @param {Number} timeout, mock async callback timeout, default is 0.
*/
function errorOnce(mod: any, method: string, error?: MockError,
function errorOnce(mod: any, method: string | symbol, error?: MockError,
props?: Record<string, any> | number,
timeout?: number) {
return _mockError(mod, method, error, props, timeout, true);
Expand All @@ -168,7 +168,7 @@ function errorOnce(mod: any, method: string, error?: MockError,
* @param {Array} datas, return datas array.
* @param {Number} timeout, mock async callback timeout, default is 10.
*/
function mockDatas(mod: any, method: string, datas: any[] | any, timeout?: number) {
function mockDatas(mod: any, method: string | symbol, datas: any[] | any, timeout?: number) {
if (timeout) {
timeout = parseInt(String(timeout), 10);
}
Expand Down Expand Up @@ -208,7 +208,7 @@ function mockDatas(mod: any, method: string, datas: any[] | any, timeout?: numbe
* @param {Object} data, return data.
* @param {Number} timeout, mock async callback timeout, default is 0.
*/
function mockData(mod: any, method: string, data: any, timeout?: number) {
function mockData(mod: any, method: string | symbol, data: any, timeout?: number) {
const isGeneratorFunction = is.generatorFunction(mod[method]);
const isAsyncFunction = is.asyncFunction(mod[method]);
if (isGeneratorFunction || isAsyncFunction) {
Expand All @@ -217,7 +217,7 @@ function mockData(mod: any, method: string, data: any, timeout?: number) {
return mockDatas(mod, method, [ data ], timeout);
}

function dataWithAsyncDispose(mod: any, method: string, data: any, timeout?: number) {
function dataWithAsyncDispose(mod: any, method: string | symbol, data: any, timeout?: number) {
data = {
...data,
async [Symbol.asyncDispose]() {
Expand All @@ -234,7 +234,7 @@ function dataWithAsyncDispose(mod: any, method: string, data: any, timeout?: num
* @param {String} method, mock module object method name.
* @param {Number} [timeout], mock async callback timeout, default is 0.
*/
function mockEmpty(mod: any, method: string, timeout?: number) {
function mockEmpty(mod: any, method: string | symbol, timeout?: number) {
return mockDatas(mod, method, [ null ], timeout);
}

Expand All @@ -243,9 +243,9 @@ function mockEmpty(mod: any, method: string, timeout?: number) {
* @param {Object} mod, module object

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 243 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"
* @param {String} method, mock module object method name.
*/
function spy(mod: any, method: string) {
function spy(mod: any, method: string | symbol) {
if (typeof mod[method] !== 'function') {
throw new Error(`spy target ${method} is not a function`);
throw new Error(`spy target ${String(method)} is not a function`);
}
const originalFn = mod[method];
const wrap = function proxy(this: any, ...args: any[]) {
Expand All @@ -262,7 +262,7 @@ function spy(mod: any, method: string) {
* @param {String|Error} error, error string message or error instance.
* @param {Object} [props], error properties
*/
function syncError(mod: any, method: string, error?: MockError, props?: Record<string, any>) {
function syncError(mod: any, method: string | symbol, error?: MockError, props?: Record<string, any>) {
error = _createError(error, props);
mock(mod, method, () => {
throw error;
Expand All @@ -276,7 +276,7 @@ function syncError(mod: any, method: string, error?: MockError, props?: Record<s
* @param {String} method, mock module object method name.
* @param {Object} data, return data.
*/
function syncData(mod: any, method: string, data?: any) {
function syncData(mod: any, method: string | symbol, data?: any) {
mock(mod, method, () => {
return data;
});
Expand All @@ -288,7 +288,7 @@ function syncData(mod: any, method: string, data?: any) {
* @param {Object} mod, module object

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (ubuntu-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (macos-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18.19.0)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 23)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 18)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 20)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"

Check warning on line 288 in src/index.ts

View workflow job for this annotation

GitHub Actions / Node.js / Test (windows-latest, 22)

Expected @param names to be "mod, method". Got "mod,, method,"
* @param {String} method, mock module object method name.
*/
function syncEmpty(mod: any, method: string) {
function syncEmpty(mod: any, method: string | symbol) {
return syncData(mod, method);
}

Expand Down Expand Up @@ -581,7 +581,7 @@ function omit(obj: Record<string, any>, key: string) {
/**
* mock class method from instance
*/
function classMethod(instance: any, property: string, value?: any) {
function classMethod(instance: any, property: PropertyKey, value?: any) {
mock(instance.constructor.prototype, property, value);
}

Expand Down
26 changes: 20 additions & 6 deletions test/mm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,23 +763,37 @@ describe('test/mm.test.js', () => {
});
});

describe('mm()', function() {

describe('mm(), mock()', function() {
it('should mock process.env.KEY work', function() {
const orginalEnv = process.env.NODE_ENV;
const originalEnv = process.env.NODE_ENV;
mm(process.env, 'NODE_ENV', 'test2');
process.env.NODE_ENV!.should.equal('test2');
mm.restore();

assert(process.env.NODE_ENV === orginalEnv);
assert(process.env.NODE_ENV === originalEnv);

mm(process.env, 'NODE_ENV', 'test2');
process.env.NODE_ENV!.should.equal('test2');
mm(process.env, 'NODE_ENV', 'production');
process.env.NODE_ENV!.should.equal('production');
mm.restore();

assert(process.env.NODE_ENV === orginalEnv);
assert(process.env.NODE_ENV === originalEnv);
});

it('should mock Symbol property work', () => {
const foo = Symbol('foo');
const data = { [foo]: 'bar' };
assert.equal(data[foo], 'bar');
mm(data, foo, 'bar1');
assert.equal(data[foo], 'bar1');
});

it('should mock number property work', () => {
const data = { 1: 'bar' };
assert.equal(data[1], 'bar');
mm(data, 1, 'bar1');
assert.equal(data[1], 'bar1');
});

it('should mm() just like muk()', function(done) {
Expand Down Expand Up @@ -830,7 +844,7 @@ describe('test/mm.test.js', () => {
});
});

it('shoud mock function with property', () => {
it('should mock function with property', () => {
const NativeDate = Date;
const mockNow = function(date: any) {
const NewDate = function(...args: any[]) {
Expand Down

0 comments on commit a7950f3

Please sign in to comment.