Skip to content

Commit

Permalink
Merge pull request #19 from uittorio/fix_class_method_without_return_…
Browse files Browse the repository at this point in the history
…type

fix bug where a mock of a method with body without specified return type was failing
  • Loading branch information
Pmyl authored Apr 6, 2019
2 parents f86792e + 5b5cda1 commit c8daaa5
Show file tree
Hide file tree
Showing 8 changed files with 859 additions and 822 deletions.
1,564 changes: 782 additions & 782 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/transformer/descriptor/descriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { GetIdentifierDescriptor } from "./identifier/identifier";
import { GetTypeParameterDescriptor } from "./typeParameter/typeParameter";
import { GetIntersectionDescriptor } from "./intersection/intersection";
import { GetFunctionTypeDescriptor } from "./method/functionType";
import { GetMethodDeclarationDescriptor } from "./method/methodDeclaration";
import {GetMethodDeclarationDescriptor} from "./method/methodDeclaration";
import { GetFunctionAssignmentDescriptor } from "./method/functionAssignment";
import { GetMockPropertiesFromSymbol } from './mock/mockProperties';
import { GetTypeAliasDescriptor } from "./typeAlias/typeAlias";
Expand All @@ -27,6 +27,7 @@ import { GetUndefinedDescriptor } from "./undefined/undefined";
import { GetMappedDescriptor } from "./mapped/mapped";
import { GetMockFactoryCall } from "../mockFactoryCall/mockFactoryCall";
import { GetTypeReferenceDescriptorReusable } from "./typeReference/typeReferenceReusable";
import {GetMethodSignatureDescriptor} from "./method/methodSignature";

export function GetDescriptor(node: ts.Node): ts.Expression {
switch (node.kind) {
Expand Down Expand Up @@ -59,7 +60,7 @@ export function GetDescriptor(node: ts.Node): ts.Expression {
case ts.SyntaxKind.ImportClause:
return GetImportDescriptor(node as ts.ImportClause);
case ts.SyntaxKind.MethodSignature:
return GetMethodDeclarationDescriptor(node as ts.MethodSignature);
return GetMethodSignatureDescriptor(node as ts.MethodSignature);
case ts.SyntaxKind.MethodDeclaration:
return GetMethodDeclarationDescriptor(node as ts.MethodDeclaration);
case ts.SyntaxKind.FunctionType:
Expand Down
5 changes: 3 additions & 2 deletions src/transformer/descriptor/interface/interfaceDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { GetDescriptor } from "../descriptor";
import { StoreGenericsFromHeritage } from '../heritage/heritage';

export function GetInterfaceDeclarationDescriptor(node: ts.InterfaceDeclaration): ts.Expression {
const typeChecker = TypeChecker();
if (IsTypescriptType(node)) {
return GetDescriptor(GetTypescriptType(node));
}

const typeChecker = TypeChecker();
const type = typeChecker.getTypeAtLocation(node);

StoreGenericsFromHeritage(node.heritageClauses);

const type = typeChecker.getTypeAtLocation(node);
let properties: Array<ts.Symbol> = typeChecker.getPropertiesOfType(type);

return GetMockPropertiesFromSymbol(properties);
Expand Down
29 changes: 29 additions & 0 deletions src/transformer/descriptor/method/bodyReturnType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as ts from "typescript";
import {GetDescriptor} from "../descriptor";
import {GetNullDescriptor} from "../null/null";

export function GetReturnTypeFromBody(node: ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration): ts.Expression {
let returnValue: ts.Expression;

const functionBody = node.body as ts.FunctionBody;

if (functionBody.statements) {
const returnStatement: ts.ReturnStatement = GetReturnStatement(functionBody);

if (returnStatement) {
returnValue = GetDescriptor(returnStatement.expression);
} else {
returnValue = GetNullDescriptor();
}
} else {
returnValue = GetDescriptor(node.body);
}

return returnValue;
}

function GetReturnStatement(body: ts.FunctionBody): ts.ReturnStatement {
return body.statements.find((statement: ts.Statement) => {
return statement.kind === ts.SyntaxKind.ReturnStatement
}) as ts.ReturnStatement
}
37 changes: 7 additions & 30 deletions src/transformer/descriptor/method/functionAssignment.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,13 @@
import * as ts from 'typescript';
import { GetDescriptor } from "../descriptor";
import { GetNullDescriptor } from "../null/null";
import { PropertySignatureCache } from "../property/cache";
import { GetMethodDescriptor } from "./method";
import {PropertySignatureCache} from "../property/cache";
import {GetMethodDescriptor} from "./method";
import {GetReturnTypeFromBody} from "./bodyReturnType";

type functionAssignment = ts.ArrowFunction | ts.FunctionExpression;

export function GetFunctionAssignmentDescriptor(node: functionAssignment): ts.Expression {
const property: ts.PropertyName = PropertySignatureCache.instance.get();
let returnValue;

const functionBody = node.body as ts.FunctionBody;

if (functionBody.statements) {
const returnStatement: ts.ReturnStatement = GetReturnStatement(functionBody);

if (returnStatement) {
returnValue = GetDescriptor(returnStatement.expression);
} else {
returnValue = GetNullDescriptor();
}

return GetMethodDescriptor(property, returnValue);
} else {
returnValue = GetDescriptor(node.body);
}

return GetMethodDescriptor(property, returnValue);
}
const property: ts.PropertyName = PropertySignatureCache.instance.get();
const returnValue = GetReturnTypeFromBody(node);

function GetReturnStatement(body: ts.FunctionBody): ts.ReturnStatement {
return body.statements.find((statement: ts.Statement) => {
return statement.kind === ts.SyntaxKind.ReturnStatement
}) as ts.ReturnStatement
}
return GetMethodDescriptor(property, returnValue);
}
18 changes: 12 additions & 6 deletions src/transformer/descriptor/method/methodDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import * as ts from 'typescript';
import { GetMethodDescriptor } from "./method";
import { GetDescriptor } from "../descriptor";
import {GetMethodDescriptor} from "./method";
import {GetDescriptor} from "../descriptor";
import {GetReturnTypeFromBody} from "./bodyReturnType";

type Methods = ts.MethodSignature | ts.MethodDeclaration;
export function GetMethodDeclarationDescriptor(node: ts.MethodDeclaration): ts.Expression {
let returnType: ts.Expression;

export function GetMethodDeclarationDescriptor(node: Methods): ts.Expression {
const returnValue: ts.Expression = GetDescriptor(node.type);
return GetMethodDescriptor(node.name, returnValue);
if (node.type) {
returnType = GetDescriptor(node.type);
} else {
returnType = GetReturnTypeFromBody(node);
}

return GetMethodDescriptor(node.name, returnType);
}
10 changes: 10 additions & 0 deletions src/transformer/descriptor/method/methodSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as ts from "typescript";
import {GetDescriptor} from "../descriptor";
import {GetMethodDescriptor} from "./method";

type Methods = ts.MethodSignature | ts.MethodDeclaration;

export function GetMethodSignatureDescriptor(node: Methods): ts.Expression {
const returnType: ts.Expression = GetDescriptor(node.type);
return GetMethodDescriptor(node.name, returnType);
}
13 changes: 13 additions & 0 deletions test/transformer/descriptor/methods/methods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ describe('for methods', () => {
});
});

describe('for undeclared return value', () => {
class MyClass {
method() {
return 2;
}
}

it('should infer the return value from return statement', () => {
const properties: MyClass = createMock<MyClass>();
expect(properties.method()).toBe(2);
});
});

describe('for a type function', () => {
type Fn = () => string;
it('should set the functions', () => {
Expand Down

0 comments on commit c8daaa5

Please sign in to comment.