From 938864be8405b15a680eab0d5159d948a0ee229b Mon Sep 17 00:00:00 2001 From: Jason Palmer Date: Tue, 1 Aug 2017 12:20:59 -0400 Subject: [PATCH 1/3] Make sure function mocks match original arity --- .../jest-mock/src/__tests__/jest_mock.test.js | 8 ++ packages/jest-mock/src/index.js | 76 ++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/packages/jest-mock/src/__tests__/jest_mock.test.js b/packages/jest-mock/src/__tests__/jest_mock.test.js index 5553a0d2eae6..b24a383260b8 100644 --- a/packages/jest-mock/src/__tests__/jest_mock.test.js +++ b/packages/jest-mock/src/__tests__/jest_mock.test.js @@ -341,6 +341,14 @@ describe('moduleMocker', () => { expect(fn1()).not.toEqual('abcd'); expect(fn2()).not.toEqual('abcd'); }); + + it('maintains function arity', () => { + const mockFunctionArity1 = moduleMocker.fn(x => x); + const mockFunctionArity2 = moduleMocker.fn((x, y) => y); + + expect(mockFunctionArity1.length).toBe(1); + expect(mockFunctionArity2.length).toBe(2); + }); }); it('supports mock value returning undefined', () => { diff --git a/packages/jest-mock/src/index.js b/packages/jest-mock/src/index.js index bdfbbf26b2c0..250c2718d8cb 100644 --- a/packages/jest-mock/src/index.js +++ b/packages/jest-mock/src/index.js @@ -19,6 +19,7 @@ export type MockFunctionMetadata = { refID?: string | number, type?: string, value?: any, + length?: number, }; type MockFunctionState = { @@ -88,6 +89,70 @@ const RESERVED_KEYWORDS = Object.assign(Object.create(null), { yield: true, }); +function matchArity(fn: any, length: number): any { + let mockConstructor; + + switch (length) { + case 0: + mockConstructor = function() { + return fn.apply(this, arguments); + }; + break; + case 1: + mockConstructor = function(a) { + return fn.apply(this, arguments); + }; + break; + case 2: + mockConstructor = function(a, b) { + return fn.apply(this, arguments); + }; + break; + case 3: + mockConstructor = function(a, b, c) { + return fn.apply(this, arguments); + }; + break; + case 4: + mockConstructor = function(a, b, c, d) { + return fn.apply(this, arguments); + }; + break; + case 5: + mockConstructor = function(a, b, c, d, e) { + return fn.apply(this, arguments); + }; + break; + case 6: + mockConstructor = function(a, b, c, d, e, f) { + return fn.apply(this, arguments); + }; + break; + case 7: + mockConstructor = function(a, b, c, d, e, f, g) { + return fn.apply(this, arguments); + }; + break; + case 8: + mockConstructor = function(a, b, c, d, e, f, g, h) { + return fn.apply(this, arguments); + }; + break; + case 9: + mockConstructor = function(a, b, c, d, e, f, g, h, i) { + return fn.apply(this, arguments); + }; + break; + default: + mockConstructor = function(a, b, c, d, e, f, g, h, i, j) { + return fn.apply(this, arguments); + }; + break; + } + + return mockConstructor; +} + function isA(typeName: string, value: any): boolean { return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; } @@ -242,7 +307,7 @@ class ModuleMockerClass { {}; const prototypeSlots = getSlots(prototype); const mocker = this; - const mockConstructor = function() { + const mockConstructor = matchArity(function() { const mockState = mocker._ensureMockState(f); const mockConfig = mocker._ensureMockConfig(f); mockState.instances.push(this); @@ -298,7 +363,7 @@ class ModuleMockerClass { } return returnValue; - }; + }, metadata.length || 0); f = this._createMockFunction(metadata, mockConstructor); f._isMockFunction = true; @@ -358,6 +423,9 @@ class ModuleMockerClass { mockConfig.isReturnValueLastSet = false; mockConfig.defaultReturnValue = undefined; mockConfig.mockImpl = fn; + + // Ensure proper arity + return f; }; @@ -431,6 +499,7 @@ class ModuleMockerClass { MOCK_CONSTRUCTOR_NAME, body, ); + return createConstructor(mockConstructor); } @@ -565,7 +634,8 @@ class ModuleMockerClass { } fn(implementation?: any): any { - const fn = this._makeComponent({type: 'function'}); + const length = implementation ? implementation.length : 0; + const fn = this._makeComponent({length, type: 'function'}); if (implementation) { fn.mockImplementation(implementation); } From e0a26b2603a0c687a49ffdc67819ca691772f26b Mon Sep 17 00:00:00 2001 From: Jason Palmer Date: Tue, 1 Aug 2017 13:42:45 -0400 Subject: [PATCH 2/3] Mocks maintain function arity with 9 or less arguments --- packages/jest-mock/src/index.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/jest-mock/src/index.js b/packages/jest-mock/src/index.js index 250c2718d8cb..11869d7acdc8 100644 --- a/packages/jest-mock/src/index.js +++ b/packages/jest-mock/src/index.js @@ -93,11 +93,6 @@ function matchArity(fn: any, length: number): any { let mockConstructor; switch (length) { - case 0: - mockConstructor = function() { - return fn.apply(this, arguments); - }; - break; case 1: mockConstructor = function(a) { return fn.apply(this, arguments); @@ -144,7 +139,7 @@ function matchArity(fn: any, length: number): any { }; break; default: - mockConstructor = function(a, b, c, d, e, f, g, h, i, j) { + mockConstructor = function() { return fn.apply(this, arguments); }; break; From 50c7544cf0692a9bbf61a682aeaf6acc134fc53d Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Wed, 2 Aug 2017 17:08:51 +0100 Subject: [PATCH 3/3] Update index.js --- packages/jest-mock/src/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/jest-mock/src/index.js b/packages/jest-mock/src/index.js index 11869d7acdc8..5f93868c173b 100644 --- a/packages/jest-mock/src/index.js +++ b/packages/jest-mock/src/index.js @@ -418,9 +418,6 @@ class ModuleMockerClass { mockConfig.isReturnValueLastSet = false; mockConfig.defaultReturnValue = undefined; mockConfig.mockImpl = fn; - - // Ensure proper arity - return f; };