Skip to content

Commit

Permalink
fix(createMockList): count the number of create mock list on runtime …
Browse files Browse the repository at this point in the history
…instead of relying on a numeric literal

Closes #595
  • Loading branch information
uittorio committed Oct 8, 2020
1 parent fb7dd2f commit eec45dd
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 54 deletions.
14 changes: 1 addition & 13 deletions src/transformer/mergeExpression/mergeExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MockDefiner } from '../mockDefiner/mockDefiner';
import { ModuleName } from '../mockDefiner/modules/moduleName';
import { PrivateIdentifier } from '../privateIdentifier/privateIdentifier';

function mergePropertyAccessor(
export function mergePropertyAccessor(
methodName: string
): ts.PropertyAccessExpression {
return ts.createPropertyAccess(
Expand All @@ -25,15 +25,3 @@ export function getMockMergeExpression(
[nodeMocked, defaultValues]
);
}

export function getMockMergeIteratorExpression(
nodeMocked: ts.Expression,
defaultValuesFunction: ts.Expression,
index: ts.NumericLiteral
): ts.Expression {
return ts.createCall(
mergePropertyAccessor('mergeIterator'),
[],
[nodeMocked, defaultValuesFunction, index]
);
}
129 changes: 88 additions & 41 deletions src/transformer/mock/mock.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import * as ts from 'typescript';
import { Logger } from '../../logger/logger';
import { ArrayHelper } from '../array/array';
import { GetDescriptor } from '../descriptor/descriptor';
import { TypescriptHelper } from '../descriptor/helper/helper';
import {
getMockMergeExpression,
getMockMergeIteratorExpression,
mergePropertyAccessor,
} from '../mergeExpression/mergeExpression';
import { MockDefiner } from '../mockDefiner/mockDefiner';
import { Scope } from '../scope/scope';
import {
MockCreateMockListLoopArray,
MockCreateMockListLoopStep,
} from '../mockIdentifier/mockIdentifier';
import { SetCurrentCreateMock } from './currentCreateMockNode';

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

function getNumberFromNumericLiteral(
numericLiteral: ts.NumericLiteral
): number {
const numericLiteralNumber: number = parseInt(numericLiteral.text, 10);
return numericLiteralNumber > 0 ? numericLiteralNumber : 0;
}

function getMockMergeListExpression(
mock: ts.Expression,
length: number,
defaultValues: ts.Expression
): ts.Expression[] {
return ArrayHelper.ArrayFromLength(length).map((index: number) =>
getMockMergeIteratorExpression(
mock,
defaultValues,
ts.createNumericLiteral('' + index.toString())
)
);
}

function getMockListExpression(
mock: ts.Expression,
length: number
): ts.Expression[] {
return ArrayHelper.ArrayFromLength(length).map(() => mock);
}

export function getMock(
nodeToMock: ts.TypeNode,
node: ts.CallExpression
Expand All @@ -69,7 +44,7 @@ export function getMock(
export function getMockForList(
nodeToMock: ts.TypeNode,
node: ts.CallExpression
): ts.ArrayLiteralExpression {
): ts.Expression {
SetCurrentCreateMock(node);
const mock: ts.Expression = getMockExpression(nodeToMock);
const lengthLiteral: ts.NumericLiteral = node
Expand All @@ -79,21 +54,93 @@ export function getMockForList(
return ts.createArrayLiteral([]);
}

const length: number = getNumberFromNumericLiteral(lengthLiteral);

if (hasDefaultListValues(node)) {
const mockMergeList: ts.Expression[] = getMockMergeListExpression(
mock,
length,
node.arguments[1]
return getListCallMock(
node.arguments[0],
ts.createCall(
mergePropertyAccessor('mergeIterator'),
[],
[mock, node.arguments[1], MockCreateMockListLoopStep]
)
);

return ts.createArrayLiteral(mockMergeList);
}

const mockList: ts.Expression[] = getMockListExpression(mock, length);
return getListCallMock(node.arguments[0], mock);
}

return ts.createArrayLiteral(mockList);
function getListCallMock(
expression: ts.Expression,
mockExpr: ts.Expression
): ts.CallExpression {
return ts.createCall(
ts.createParen(
ts.createFunctionExpression(
undefined,
undefined,
undefined,
undefined,
[],
undefined,
ts.createBlock(
[
ts.createVariableStatement(
undefined,
ts.createVariableDeclarationList(
[
ts.createVariableDeclaration(
MockCreateMockListLoopArray,
undefined,
ts.createArrayLiteral([], false)
),
],
ts.NodeFlags.Const
)
),
ts.createFor(
ts.createVariableDeclarationList(
[
ts.createVariableDeclaration(
MockCreateMockListLoopStep,
undefined,
ts.createNumericLiteral('0')
),
],
ts.NodeFlags.Let
),
ts.createBinary(
MockCreateMockListLoopStep,
ts.createToken(ts.SyntaxKind.LessThanToken),
expression
),
ts.createPostfix(
MockCreateMockListLoopStep,
ts.SyntaxKind.PlusPlusToken
),
ts.createBlock(
[
ts.createExpressionStatement(
ts.createCall(
ts.createPropertyAccess(
MockCreateMockListLoopArray,
ts.createIdentifier('push')
),
undefined,
[mockExpr]
)
),
],
true
)
),
ts.createReturn(MockCreateMockListLoopArray),
],
true
)
)
),
undefined,
[]
);
}

export function storeRegisterMock(
Expand Down
7 changes: 7 additions & 0 deletions src/transformer/mockIdentifier/mockIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,10 @@ export const MockIdentifierSetParameterName: ts.Identifier = ts.createIdentifier
export const MockCallAnonymousText: string = '*';
export const MockCallLiteralText: string = 'L';
export const MockPrivatePrefix: string = 'ɵ';

export const MockCreateMockListLoopStep: ts.Identifier = ts.createIdentifier(
'k'
);
export const MockCreateMockListLoopArray: ts.Identifier = ts.createIdentifier(
's'
);
16 changes: 16 additions & 0 deletions test/frameworkContext/create-mock-list-values.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,20 @@ describe('create-mock-list-values', () => {
expect(properties[1].property.a).toBe(2);
expect(properties[2].property.a).toBe(4);
});

it('should create a list of mocks when the count of mocks is not literal', () => {
function two(): number {
return 2;
}

const mockList: Interface[] = createMockList<Interface>(
two(),
(index: number) => ({
property: {
a: index * 2,
},
})
);
expect(mockList.length).toBe(2);
});
});
24 changes: 24 additions & 0 deletions test/frameworkContext/create-mock-list.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createMockList } from 'ts-auto-mock';
import { getTwo } from './utils/function.test';

describe('create-mock-list', () => {
interface Interface {
Expand All @@ -12,4 +13,27 @@ describe('create-mock-list', () => {
expect(properties[0].method).toHaveBeenCalled();
expect(properties[1].method).not.toHaveBeenCalled();
});

it('should create a list of mocks when the number is calculated from a function', () => {
function two(): number {
return 2;
}

const mockList: Interface[] = createMockList<Interface>(two());
expect(mockList.length).toBe(2);
expect(mockList[1].property).toBe('');
});

it('should create a list of mocks when the number is calculated from a function imported', () => {
const mockList: Interface[] = createMockList<Interface>(getTwo());
expect(mockList.length).toBe(2);
expect(mockList[1].property).toBe('');
});

it('should create a list of mocks when the number is in a variable', () => {
const numberOfMocks: number = 3;
const mockList: Interface[] = createMockList<Interface>(numberOfMocks);
expect(mockList.length).toBe(3);
expect(mockList[0].property).toBe('');
});
});
3 changes: 3 additions & 0 deletions test/frameworkContext/utils/function.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getTwo(): number {
return 2;
}

0 comments on commit eec45dd

Please sign in to comment.