Skip to content

Commit eec45dd

Browse files
committed
fix(createMockList): count the number of create mock list on runtime instead of relying on a numeric literal
Closes #595
1 parent fb7dd2f commit eec45dd

File tree

6 files changed

+139
-54
lines changed

6 files changed

+139
-54
lines changed

src/transformer/mergeExpression/mergeExpression.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { MockDefiner } from '../mockDefiner/mockDefiner';
33
import { ModuleName } from '../mockDefiner/modules/moduleName';
44
import { PrivateIdentifier } from '../privateIdentifier/privateIdentifier';
55

6-
function mergePropertyAccessor(
6+
export function mergePropertyAccessor(
77
methodName: string
88
): ts.PropertyAccessExpression {
99
return ts.createPropertyAccess(
@@ -25,15 +25,3 @@ export function getMockMergeExpression(
2525
[nodeMocked, defaultValues]
2626
);
2727
}
28-
29-
export function getMockMergeIteratorExpression(
30-
nodeMocked: ts.Expression,
31-
defaultValuesFunction: ts.Expression,
32-
index: ts.NumericLiteral
33-
): ts.Expression {
34-
return ts.createCall(
35-
mergePropertyAccessor('mergeIterator'),
36-
[],
37-
[nodeMocked, defaultValuesFunction, index]
38-
);
39-
}

src/transformer/mock/mock.ts

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import * as ts from 'typescript';
22
import { Logger } from '../../logger/logger';
3-
import { ArrayHelper } from '../array/array';
43
import { GetDescriptor } from '../descriptor/descriptor';
54
import { TypescriptHelper } from '../descriptor/helper/helper';
65
import {
76
getMockMergeExpression,
8-
getMockMergeIteratorExpression,
7+
mergePropertyAccessor,
98
} from '../mergeExpression/mergeExpression';
109
import { MockDefiner } from '../mockDefiner/mockDefiner';
1110
import { Scope } from '../scope/scope';
11+
import {
12+
MockCreateMockListLoopArray,
13+
MockCreateMockListLoopStep,
14+
} from '../mockIdentifier/mockIdentifier';
1215
import { SetCurrentCreateMock } from './currentCreateMockNode';
1316

1417
function getMockExpression(nodeToMock: ts.TypeNode): ts.Expression {
@@ -23,34 +26,6 @@ function hasDefaultListValues(node: ts.CallExpression): boolean {
2326
return !!node.arguments[1];
2427
}
2528

26-
function getNumberFromNumericLiteral(
27-
numericLiteral: ts.NumericLiteral
28-
): number {
29-
const numericLiteralNumber: number = parseInt(numericLiteral.text, 10);
30-
return numericLiteralNumber > 0 ? numericLiteralNumber : 0;
31-
}
32-
33-
function getMockMergeListExpression(
34-
mock: ts.Expression,
35-
length: number,
36-
defaultValues: ts.Expression
37-
): ts.Expression[] {
38-
return ArrayHelper.ArrayFromLength(length).map((index: number) =>
39-
getMockMergeIteratorExpression(
40-
mock,
41-
defaultValues,
42-
ts.createNumericLiteral('' + index.toString())
43-
)
44-
);
45-
}
46-
47-
function getMockListExpression(
48-
mock: ts.Expression,
49-
length: number
50-
): ts.Expression[] {
51-
return ArrayHelper.ArrayFromLength(length).map(() => mock);
52-
}
53-
5429
export function getMock(
5530
nodeToMock: ts.TypeNode,
5631
node: ts.CallExpression
@@ -69,7 +44,7 @@ export function getMock(
6944
export function getMockForList(
7045
nodeToMock: ts.TypeNode,
7146
node: ts.CallExpression
72-
): ts.ArrayLiteralExpression {
47+
): ts.Expression {
7348
SetCurrentCreateMock(node);
7449
const mock: ts.Expression = getMockExpression(nodeToMock);
7550
const lengthLiteral: ts.NumericLiteral = node
@@ -79,21 +54,93 @@ export function getMockForList(
7954
return ts.createArrayLiteral([]);
8055
}
8156

82-
const length: number = getNumberFromNumericLiteral(lengthLiteral);
83-
8457
if (hasDefaultListValues(node)) {
85-
const mockMergeList: ts.Expression[] = getMockMergeListExpression(
86-
mock,
87-
length,
88-
node.arguments[1]
58+
return getListCallMock(
59+
node.arguments[0],
60+
ts.createCall(
61+
mergePropertyAccessor('mergeIterator'),
62+
[],
63+
[mock, node.arguments[1], MockCreateMockListLoopStep]
64+
)
8965
);
90-
91-
return ts.createArrayLiteral(mockMergeList);
9266
}
9367

94-
const mockList: ts.Expression[] = getMockListExpression(mock, length);
68+
return getListCallMock(node.arguments[0], mock);
69+
}
9570

96-
return ts.createArrayLiteral(mockList);
71+
function getListCallMock(
72+
expression: ts.Expression,
73+
mockExpr: ts.Expression
74+
): ts.CallExpression {
75+
return ts.createCall(
76+
ts.createParen(
77+
ts.createFunctionExpression(
78+
undefined,
79+
undefined,
80+
undefined,
81+
undefined,
82+
[],
83+
undefined,
84+
ts.createBlock(
85+
[
86+
ts.createVariableStatement(
87+
undefined,
88+
ts.createVariableDeclarationList(
89+
[
90+
ts.createVariableDeclaration(
91+
MockCreateMockListLoopArray,
92+
undefined,
93+
ts.createArrayLiteral([], false)
94+
),
95+
],
96+
ts.NodeFlags.Const
97+
)
98+
),
99+
ts.createFor(
100+
ts.createVariableDeclarationList(
101+
[
102+
ts.createVariableDeclaration(
103+
MockCreateMockListLoopStep,
104+
undefined,
105+
ts.createNumericLiteral('0')
106+
),
107+
],
108+
ts.NodeFlags.Let
109+
),
110+
ts.createBinary(
111+
MockCreateMockListLoopStep,
112+
ts.createToken(ts.SyntaxKind.LessThanToken),
113+
expression
114+
),
115+
ts.createPostfix(
116+
MockCreateMockListLoopStep,
117+
ts.SyntaxKind.PlusPlusToken
118+
),
119+
ts.createBlock(
120+
[
121+
ts.createExpressionStatement(
122+
ts.createCall(
123+
ts.createPropertyAccess(
124+
MockCreateMockListLoopArray,
125+
ts.createIdentifier('push')
126+
),
127+
undefined,
128+
[mockExpr]
129+
)
130+
),
131+
],
132+
true
133+
)
134+
),
135+
ts.createReturn(MockCreateMockListLoopArray),
136+
],
137+
true
138+
)
139+
)
140+
),
141+
undefined,
142+
[]
143+
);
97144
}
98145

99146
export function storeRegisterMock(

src/transformer/mockIdentifier/mockIdentifier.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,10 @@ export const MockIdentifierSetParameterName: ts.Identifier = ts.createIdentifier
2121
export const MockCallAnonymousText: string = '*';
2222
export const MockCallLiteralText: string = 'L';
2323
export const MockPrivatePrefix: string = 'ɵ';
24+
25+
export const MockCreateMockListLoopStep: ts.Identifier = ts.createIdentifier(
26+
'k'
27+
);
28+
export const MockCreateMockListLoopArray: ts.Identifier = ts.createIdentifier(
29+
's'
30+
);

test/frameworkContext/create-mock-list-values.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,20 @@ describe('create-mock-list-values', () => {
3030
expect(properties[1].property.a).toBe(2);
3131
expect(properties[2].property.a).toBe(4);
3232
});
33+
34+
it('should create a list of mocks when the count of mocks is not literal', () => {
35+
function two(): number {
36+
return 2;
37+
}
38+
39+
const mockList: Interface[] = createMockList<Interface>(
40+
two(),
41+
(index: number) => ({
42+
property: {
43+
a: index * 2,
44+
},
45+
})
46+
);
47+
expect(mockList.length).toBe(2);
48+
});
3349
});

test/frameworkContext/create-mock-list.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createMockList } from 'ts-auto-mock';
2+
import { getTwo } from './utils/function.test';
23

34
describe('create-mock-list', () => {
45
interface Interface {
@@ -12,4 +13,27 @@ describe('create-mock-list', () => {
1213
expect(properties[0].method).toHaveBeenCalled();
1314
expect(properties[1].method).not.toHaveBeenCalled();
1415
});
16+
17+
it('should create a list of mocks when the number is calculated from a function', () => {
18+
function two(): number {
19+
return 2;
20+
}
21+
22+
const mockList: Interface[] = createMockList<Interface>(two());
23+
expect(mockList.length).toBe(2);
24+
expect(mockList[1].property).toBe('');
25+
});
26+
27+
it('should create a list of mocks when the number is calculated from a function imported', () => {
28+
const mockList: Interface[] = createMockList<Interface>(getTwo());
29+
expect(mockList.length).toBe(2);
30+
expect(mockList[1].property).toBe('');
31+
});
32+
33+
it('should create a list of mocks when the number is in a variable', () => {
34+
const numberOfMocks: number = 3;
35+
const mockList: Interface[] = createMockList<Interface>(numberOfMocks);
36+
expect(mockList.length).toBe(3);
37+
expect(mockList[0].property).toBe('');
38+
});
1539
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function getTwo(): number {
2+
return 2;
3+
}

0 commit comments

Comments
 (0)