diff --git a/src/transformer/descriptor/boolean/booleanFalse.ts b/src/transformer/descriptor/boolean/booleanFalse.ts index 478e68d0d..7c5207cdf 100644 --- a/src/transformer/descriptor/boolean/booleanFalse.ts +++ b/src/transformer/descriptor/boolean/booleanFalse.ts @@ -1,5 +1,5 @@ import * as ts from 'typescript'; export function GetBooleanFalseDescriptor(): ts.Expression { - return ts.createLiteral(false); + return ts.createLogicalNot(ts.createLiteral(1)); } diff --git a/src/transformer/descriptor/boolean/booleanTrue.ts b/src/transformer/descriptor/boolean/booleanTrue.ts index 0aff537e5..a6f0b32df 100644 --- a/src/transformer/descriptor/boolean/booleanTrue.ts +++ b/src/transformer/descriptor/boolean/booleanTrue.ts @@ -1,5 +1,5 @@ import * as ts from 'typescript'; export function GetBooleanTrueDescriptor(): ts.Expression { - return ts.createLiteral(true); + return ts.createLogicalNot(ts.createLiteral(0)); } diff --git a/src/transformer/descriptor/mock/mockCall.ts b/src/transformer/descriptor/mock/mockCall.ts index ba74c3cba..c87d3b537 100644 --- a/src/transformer/descriptor/mock/mockCall.ts +++ b/src/transformer/descriptor/mock/mockCall.ts @@ -2,22 +2,31 @@ import * as ts from 'typescript'; import { TypescriptCreator } from '../../helper/creator'; import { MockIdentifierInternalValues, MockIdentifierObjectReturnValue } from '../../mockIdentifier/mockIdentifier'; import { GetMockMarkerProperty, Property } from './mockMarker'; +import { PropertyAssignments } from './mockPropertiesAssignments'; -export function GetMockCall(properties: ts.PropertyAssignment[], signature: ts.Expression): ts.CallExpression { +export function GetMockCall(properties: PropertyAssignments, signature: ts.Expression): ts.CallExpression { const mockObjectReturnValueName: ts.Identifier = MockIdentifierObjectReturnValue; const statements: ts.Statement[] = [ ts.createVariableStatement([], [ TypescriptCreator.createVariableDeclaration(MockIdentifierInternalValues, ts.createObjectLiteral()), - TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, ts.createObjectLiteral()), + TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, signature || ts.createObjectLiteral(properties.literals)), ]), ]; if (signature) { - statements.push(AssignVariableTo(mockObjectReturnValueName, signature)); + let literalProperty: ts.PropertyAssignment; + let index: number = 0; + + // tslint:disable-next-line:no-conditional-assignment + while ((literalProperty = properties.literals[index++])) { + statements.push(AssignLiteralPropertyTo(mockObjectReturnValueName, literalProperty)); + } } - const addPropertiesToUniqueVariable: ts.ExpressionStatement = AssignPropertiesTo(properties, mockObjectReturnValueName); - statements.push(addPropertiesToUniqueVariable); + if (properties.lazy.length) { + const addPropertiesToUniqueVariable: ts.ExpressionStatement = AssignPropertiesTo(properties.lazy, mockObjectReturnValueName); + statements.push(addPropertiesToUniqueVariable); + } const addMockMarkerToUniqueVariable: ts.ExpressionStatement = AssignMockMarkerPropertyTo(mockObjectReturnValueName); statements.push(addMockMarkerToUniqueVariable); @@ -30,11 +39,16 @@ export function GetMockCall(properties: ts.PropertyAssignment[], signature: ts.E return ts.createCall(IFFEFunction, [], []); } -function AssignVariableTo(variable: ts.Identifier, expression: ts.Expression): ts.ExpressionStatement { +function AssignVariableTo(variable: ts.Expression, expression: ts.Expression): ts.ExpressionStatement { const binaryExpression: ts.BinaryExpression = ts.createBinary(variable, ts.SyntaxKind.EqualsToken, expression); return ts.createExpressionStatement(binaryExpression); } +function AssignLiteralPropertyTo(mockObjectReturnValueName: ts.Identifier, literalProperty: ts.PropertyAssignment): ts.ExpressionStatement { + const propertyAccess: ts.ElementAccessExpression = ts.createElementAccess(mockObjectReturnValueName, literalProperty.name as ts.StringLiteral); + return AssignVariableTo(propertyAccess, literalProperty.initializer); +} + function AssignMockMarkerPropertyTo(identifier: ts.Identifier): ts.ExpressionStatement { const mockMarkerProperty: Property = GetMockMarkerProperty(); diff --git a/src/transformer/descriptor/mock/mockMarker.ts b/src/transformer/descriptor/mock/mockMarker.ts index d60f76847..70048ee66 100644 --- a/src/transformer/descriptor/mock/mockMarker.ts +++ b/src/transformer/descriptor/mock/mockMarker.ts @@ -1,6 +1,7 @@ import * as ts from 'typescript'; import { MockDefiner } from '../../mockDefiner/mockDefiner'; import { ModuleName } from '../../mockDefiner/modules/moduleName'; +import { GetBooleanTrueDescriptor } from '../boolean/booleanTrue'; export interface Property { name: ts.Expression; @@ -21,6 +22,6 @@ export function GetMockMarkerProperty(): Property { return { name: mockMarkerCall, - value: ts.createLiteral(true), + value: GetBooleanTrueDescriptor(), }; } diff --git a/src/transformer/descriptor/mock/mockProperties.ts b/src/transformer/descriptor/mock/mockProperties.ts index 1dbe897c3..9ea2e1546 100644 --- a/src/transformer/descriptor/mock/mockProperties.ts +++ b/src/transformer/descriptor/mock/mockProperties.ts @@ -3,7 +3,7 @@ import { Scope } from '../../scope/scope'; import { GetDescriptor } from '../descriptor'; import { IsTypescriptType } from '../tsLibs/typecriptLibs'; import { GetMockCall } from './mockCall'; -import { GetMockProperty } from './mockProperty'; +import { GetMockPropertiesAssignments, PropertyAssignments } from './mockPropertiesAssignments'; import { PropertyLike } from './propertyLike'; import { SignatureLike } from './signatureLike'; @@ -36,11 +36,7 @@ export function GetMockPropertiesFromDeclarations(list: ReadonlyArray { - return GetMockProperty(member, scope); - }, - ); + const accessorDeclaration: PropertyAssignments = GetMockPropertiesAssignments(propertiesFilter, scope); const signaturesDescriptor: ts.Expression = signatures.length > 0 ? GetDescriptor(signatures[0], scope) : null; return GetMockCall(accessorDeclaration, signaturesDescriptor); diff --git a/src/transformer/descriptor/mock/mockProperty.ts b/src/transformer/descriptor/mock/mockPropertiesAssignments.ts similarity index 59% rename from src/transformer/descriptor/mock/mockProperty.ts rename to src/transformer/descriptor/mock/mockPropertiesAssignments.ts index 33bf3fdc7..bbe301fe2 100644 --- a/src/transformer/descriptor/mock/mockProperty.ts +++ b/src/transformer/descriptor/mock/mockPropertiesAssignments.ts @@ -2,13 +2,44 @@ import * as ts from 'typescript'; import { TypescriptCreator } from '../../helper/creator'; import { MockIdentifierInternalValues, MockIdentifierSetParameterName } from '../../mockIdentifier/mockIdentifier'; import { Scope } from '../../scope/scope'; +import { GetBooleanTrueDescriptor } from '../boolean/booleanTrue'; import { GetDescriptor } from '../descriptor'; import { TypescriptHelper } from '../helper/helper'; import { PropertyLike } from './propertyLike'; -export function GetMockProperty(member: PropertyLike, scope: Scope): ts.PropertyAssignment { - const descriptor: ts.Expression = GetDescriptor(member, scope); +export interface PropertyAssignments { + lazy: ts.PropertyAssignment[]; + literals: ts.PropertyAssignment[]; +} + +export function GetMockPropertiesAssignments(properties: PropertyLike[], scope: Scope): PropertyAssignments { + return properties.reduce( + (acc: PropertyAssignments, member: PropertyLike): PropertyAssignments => { + const descriptor: ts.Expression = GetDescriptor(member, scope); + + if (descriptor.kind === ts.SyntaxKind.VoidExpression) { + return acc; + } + + if (ts.isCallLikeExpression(descriptor)) { + acc.lazy.push(GetLazyMockProperty(descriptor, member)); + } else { + acc.literals.push(GetLiteralMockProperty(descriptor, member)); + } + + return acc; + }, + { lazy: [], literals: []}, + ); +} + +function GetLiteralMockProperty(descriptor: ts.Expression, member: PropertyLike): ts.PropertyAssignment { + const propertyName: string = TypescriptHelper.GetStringPropertyName(member.name); + + return ts.createPropertyAssignment(ts.createStringLiteral(propertyName), descriptor); +} +function GetLazyMockProperty(descriptor: ts.Expression, member: PropertyLike): ts.PropertyAssignment { const propertyName: string = TypescriptHelper.GetStringPropertyName(member.name); const variableDeclarationName: ts.ElementAccessExpression = ts.createElementAccess(MockIdentifierInternalValues, ts.createStringLiteral(propertyName)); @@ -29,7 +60,7 @@ export function GetMockProperty(member: PropertyLike, scope: Scope): ts.Property const set: ts.MethodDeclaration = TypescriptCreator.createMethod('set', setBody, [setVariableParameterName]); const literal: ts.ObjectLiteralExpression = ts.createObjectLiteral([get, set, ts.createPropertyAssignment( ts.createIdentifier('enumerable'), - ts.createTrue(), + GetBooleanTrueDescriptor(), )]); return ts.createPropertyAssignment(ts.createStringLiteral(propertyName), literal); diff --git a/src/transformer/descriptor/undefined/undefined.ts b/src/transformer/descriptor/undefined/undefined.ts index b52b58924..81abe53a3 100644 --- a/src/transformer/descriptor/undefined/undefined.ts +++ b/src/transformer/descriptor/undefined/undefined.ts @@ -1,5 +1,5 @@ import * as ts from 'typescript'; export function GetUndefinedDescriptor(): ts.Expression { - return ts.createIdentifier('undefined'); + return ts.createVoidZero(); } diff --git a/src/transformer/mockDefiner/factoryUniqueName.ts b/src/transformer/mockDefiner/factoryUniqueName.ts index ae5462a0c..0576c382d 100644 --- a/src/transformer/mockDefiner/factoryUniqueName.ts +++ b/src/transformer/mockDefiner/factoryUniqueName.ts @@ -1,4 +1,5 @@ import * as ts from 'typescript'; +import { MockCallAnonymousText, MockCallLiteralText } from '../mockIdentifier/mockIdentifier'; import { KeyCounter } from './keyCounter'; export type PossibleDeclaration = ts.InterfaceDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration; @@ -12,17 +13,14 @@ export class FactoryUniqueName { public createForDeclaration(declaration: PossibleDeclaration): string { const declarationNameIdentifier: ts.Identifier = declaration.name; - const declarationNameSanitized: string = (declarationNameIdentifier && declarationNameIdentifier.text) || 'Anonymous'; - const baseFactoryName: string = `create__${declarationNameSanitized}__mock`; - const count: number = this._keyCounter.getFor(baseFactoryName); - return `${baseFactoryName}_${count}`; + return this.createUniqueName(declarationNameIdentifier && declarationNameIdentifier.text); } public createForIntersection(nodes: ts.Node[]): string { const nameOfDeclarations: string = nodes.reduce((acc: string, declaration: ts.Node) => { if (ts.isTypeLiteralNode(declaration)) { - acc += 'literal'; + acc += MockCallLiteralText; } if (ts.isInterfaceDeclaration(declaration) || ts.isTypeAliasDeclaration(declaration) || ts.isClassDeclaration(declaration)) { @@ -32,8 +30,12 @@ export class FactoryUniqueName { return acc; }, ''); - const declarationNameSanitized: string = nameOfDeclarations || 'Anonymous'; - const baseFactoryName: string = `create__${declarationNameSanitized}__mock`; + return this.createUniqueName(nameOfDeclarations); + } + + private createUniqueName(name?: string): string { + const declarationNameSanitized: string = name || MockCallAnonymousText; + const baseFactoryName: string = `@${declarationNameSanitized}`; const count: number = this._keyCounter.getFor(baseFactoryName); return `${baseFactoryName}_${count}`; diff --git a/src/transformer/mockIdentifier/mockIdentifier.ts b/src/transformer/mockIdentifier/mockIdentifier.ts index 572c76047..59e7e96eb 100644 --- a/src/transformer/mockIdentifier/mockIdentifier.ts +++ b/src/transformer/mockIdentifier/mockIdentifier.ts @@ -6,3 +6,5 @@ export const MockIdentifierGenericParameterValue: ts.Identifier = ts.createIdent export const MockIdentifierInternalValues: ts.Identifier = ts.createIdentifier('d'); export const MockIdentifierObjectReturnValue: ts.Identifier = ts.createIdentifier('m'); export const MockIdentifierSetParameterName: ts.Identifier = ts.createIdentifier('v'); +export const MockCallAnonymousText: string = '*'; +export const MockCallLiteralText: string = 'L';