Skip to content

Commit

Permalink
feat(constructorType): Add constructor type descriptor (#115)
Browse files Browse the repository at this point in the history
* feat(constructorType): add constructor type descriptor

* update documentation adding support to constructor type

* add unit test to cover type
  • Loading branch information
Pmyl committed Dec 3, 2019
1 parent af88678 commit 8f26218
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 15 deletions.
7 changes: 7 additions & 0 deletions config/karma/karma.config.transformer.playground.build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const karmaBaseConfig = require('./karma.config.base');

module.exports = function(config) {
const karmaConfig = karmaBaseConfig(config, '../../test/playground/**/*.test.js');

config.set(karmaConfig);
};
14 changes: 13 additions & 1 deletion docs/DETAILS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mock.name // ""
```
## Classes
```ts
interface Person {
class Person {
private _id: string;
name: string
}
Expand Down Expand Up @@ -212,3 +212,15 @@ interface Interface {
const mock = createMock<Interface>();
mock // { intersection: { a: "", b: 0 } }
```
## ConstructorType
```ts
interface Test {
a: string;
}
const mockType = createMock<new () => Test>();
const mock = new mockType();
mock = // { a: "" }
```
12 changes: 0 additions & 12 deletions docs/NOT_SUPPORTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,6 @@ const mock = createMock<Test>();
mock.conditional // should be string. It will be null
```

## ConstructorType

This scenario needs to be investigated

```ts
interface Test {
toConstructor(): new (): Test
}
const mock = createMock<Test>();
mock.toConstructor() // will be null
```

## TypeQuery
[bug](https://github.com/uittorio/ts-auto-mock/issues/91)

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"test:unit": "karma start config/karma/karma.config.unit.js",
"test:transformer": "karma start config/karma/karma.config.transformer.js",
"test:playground": "karma start config/karma/karma.config.transformer.playground.js",
"test:playground:build": "karma start config/karma/karma.config.transformer.playground.build.js",
"test:framework:context": "karma start config/karma/karma.config.framework.context.js",
"test:frameworkDeprecated": "karma start config/karma/karma.config.framework.deprecated.js",
"test:framework": "karma start config/karma/karma.config.framework.js DISABLECACHE=true",
Expand Down
8 changes: 8 additions & 0 deletions src/transformer/descriptor/constructor/constructorType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as ts from 'typescript';
import { TypescriptCreator } from '../../helper/creator';
import { Scope } from '../../scope/scope';
import { GetDescriptor } from '../descriptor';

export function GetConstructorTypeDescriptor(node: ts.ConstructorTypeNode, scope: Scope): ts.Expression {
return TypescriptCreator.createFunctionExpressionReturn(GetDescriptor(node.type, scope));
}
3 changes: 3 additions & 0 deletions src/transformer/descriptor/descriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GetBooleanDescriptor } from './boolean/boolean';
import { GetBooleanFalseDescriptor } from './boolean/booleanFalse';
import { GetBooleanTrueDescriptor } from './boolean/booleanTrue';
import { GetClassDeclarationDescriptor } from './class/classDeclaration';
import { GetConstructorTypeDescriptor } from './constructor/constructorType';
import { GetEnumDeclarationDescriptor } from './enum/enumDeclaration';
import { GetExpressionWithTypeArgumentsDescriptor } from './expression/expressionWithTypeArguments';
import { GetIdentifierDescriptor } from './identifier/identifier';
Expand Down Expand Up @@ -74,6 +75,8 @@ export function GetDescriptor(node: ts.Node, scope: Scope): ts.Expression {
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.FunctionExpression:
return GetFunctionAssignmentDescriptor(node as ts.ArrowFunction, scope);
case ts.SyntaxKind.ConstructorType:
return GetConstructorTypeDescriptor(node as ts.ConstructorTypeNode, scope);
case ts.SyntaxKind.UnionType:
return GetUnionDescriptor(node as ts.UnionTypeNode, scope);
case ts.SyntaxKind.IntersectionType:
Expand Down
9 changes: 7 additions & 2 deletions test/playground/playground.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import { createMock } from 'ts-auto-mock';
*/

it('should work', () => {
interface Newable {
b: string;
}

interface Interface {
a: string;
a: new () => Newable;
b: Newable;
}

const properties: Interface = createMock<Interface>();

expect(properties.a).toEqual('');
expect(new (properties.a)().b).toEqual('');
});
102 changes: 102 additions & 0 deletions test/transformer/descriptor/constructor/constructorType.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { createMock } from 'ts-auto-mock';

describe('constructorType', () => {
describe('of an interface', () => {
it('should create a concrete newable type of the interface', () => {
interface Test {
a: string;
b: number;
}

const mockConstructorType: new () => Test = createMock<new () => Test>();
const mockInstance: Test = new mockConstructorType();

expect(mockInstance.a).toEqual('');
expect(mockInstance.b).toEqual(0);
});

it('should not create a singleton newable type of the interface', () => {
interface Test {
a: string;
b: number;
}

const mockConstructorType: new () => Test = createMock<new () => Test>();
const mockInstance1: Test = new mockConstructorType();
const mockInstance2: Test = new mockConstructorType();
const mockInstance3: Test = new mockConstructorType();

mockInstance1.a = 'test1';
mockInstance2.a = 'test2';
mockInstance3.a = 'test3';

expect(mockInstance1.a).toEqual('test1');
expect(mockInstance2.a).toEqual('test2');
expect(mockInstance3.a).toEqual('test3');
});
});

describe('of a class', () => {
it('should create a concrete newable type of the class', () => {
class Test {
a: string;
b: number;
}

const mockConstructorType: new () => Test = createMock<new () => Test>();
const mockInstance: Test = new mockConstructorType();

expect(mockInstance.a).toEqual('');
expect(mockInstance.b).toEqual(0);
});
});

describe('in a property', () => {
it('should create a concrete newable type in the property', () => {
interface Test {
a: string;
b: number;
c: new () => Test;
}

const mock: Test = createMock<Test>();
const instance: Test = new mock.c();

expect(instance.a).toEqual('');
expect(instance.b).toEqual(0);
});
});

describe('in a method', () => {
it('should create a concrete newable type as a method returned value', () => {
interface Test {
a: string;
b: number;
c(): new () => Test;
}

const mock: Test = createMock<Test>();
const instance: Test = new (mock.c())();

expect(instance.a).toEqual('');
expect(instance.b).toEqual(0);
});
});

describe('from a type', () => {
it('should create a concrete newable type', () => {
interface Test {
a: string;
b: number;
}

type TestType = new () => Test;

const mockType: TestType = createMock<TestType>();
const instance: Test = new mockType();

expect(instance.a).toEqual('');
expect(instance.b).toEqual(0);
});
});
});

0 comments on commit 8f26218

Please sign in to comment.