Skip to content

Commit

Permalink
fix(registerMock): allow to use mocks defined in variables (#330)
Browse files Browse the repository at this point in the history
* fix(registerMock): allow to use mocks defined in variables

* test(registerMock): fix wrong test description

Co-authored-by: Vittorio Guerriero <[email protected]>
  • Loading branch information
marcmrf and uittorio authored Jun 10, 2020
1 parent 2b1c8cd commit b14bd5c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 36 deletions.
5 changes: 2 additions & 3 deletions src/transformer/mock/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ export function getMockForList(nodeToMock: ts.TypeNode, node: ts.CallExpression)
export function storeRegisterMock(typeToMock: ts.TypeNode, node: ts.CallExpression): ts.Node {
if (ts.isTypeReferenceNode(typeToMock)) {
const factory: ts.FunctionExpression = node.arguments[0] as ts.FunctionExpression;
MockDefiner.instance.storeRegisterMockFor(TypescriptHelper.GetDeclarationFromNode(typeToMock.typeName), factory);
return MockDefiner.instance.registerMockFor(TypescriptHelper.GetDeclarationFromNode(typeToMock.typeName), factory);
} else {
Logger('RegisterMock').error('registerMock can be used only to mock type references.');
return ts.createEmptyStatement();
}

return ts.createEmptyStatement();
}
46 changes: 13 additions & 33 deletions src/transformer/mockDefiner/mockDefiner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export class MockDefiner {
private _neededImportIdentifierPerFile: { [key: string]: Array<ModuleNameIdentifier> } = {};
private _internalModuleImportIdentifierPerFile: { [key: string]: { [key in ModuleName]: ts.Identifier } } = {};
private _factoryRegistrationsPerFile: FactoryRegistrationPerFile = {};
private _registerMockFactoryRegistrationsPerFile: FactoryRegistrationPerFile = {};
private _factoryIntersectionsRegistrationsPerFile: FactoryIntersectionRegistrationPerFile = {};
private _factoryCache: DeclarationCache;
private _registerMockFactoryCache: DeclarationCache;
Expand Down Expand Up @@ -93,7 +92,6 @@ export class MockDefiner {
...this._getImportsToAddInFile(sourceFile),
...this._getExportsToAddInFile(sourceFile),
...this._getExportsIntersectionToAddInFile(sourceFile),
...this._getRegisterMockInFile(sourceFile),
];
}

Expand All @@ -105,7 +103,6 @@ export class MockDefiner {
}
this._factoryRegistrationsPerFile[sourceFile.fileName] = [];
this._factoryIntersectionsRegistrationsPerFile[sourceFile.fileName] = [];
this._registerMockFactoryRegistrationsPerFile[sourceFile.fileName] = [];
}

public createMockFactory(declaration: ts.Declaration): void {
Expand Down Expand Up @@ -157,16 +154,12 @@ export class MockDefiner {
return this._declarationCache.get(declaration) as string;
}

public storeRegisterMockFor(declaration: ts.Declaration, factory: ts.FunctionExpression): void {
public registerMockFor(declaration: ts.Declaration, factory: ts.FunctionExpression): ts.Node {
const key: string = this.getDeclarationKeyMap(declaration);

this._registerMockFactoryCache.set(declaration, key);

this._registerMockFactoryRegistrationsPerFile[this._fileName] = this._registerMockFactoryRegistrationsPerFile[this._fileName] || [];
this._registerMockFactoryRegistrationsPerFile[this._fileName].push({
key: declaration,
factory,
});
return this._getCallRegisterMock(this._fileName, key, factory);
}

public hasMockForDeclaration(declaration: ts.Declaration): boolean {
Expand Down Expand Up @@ -283,33 +276,20 @@ export class MockDefiner {
return [];
}

private _getRegisterMockInFile(sourceFile: ts.SourceFile): ts.Statement[] {
if (this._registerMockFactoryRegistrationsPerFile[sourceFile.fileName]) {
return this._registerMockFactoryRegistrationsPerFile[sourceFile.fileName]
.map((reg: { key: ts.Declaration; factory: ts.Expression }) => {
// NOTE: this._registerMockFactoryCache and
// this._registerMockFactoryCache are populated in the same routine
// and if the former is defined the latter will be too!
// eslint-disable-next-line
const key: string = this._registerMockFactoryCache.get(reg.key)!;

return this._createRegistration(sourceFile.fileName, key, reg.factory);
});
}

return [];
}

private _createRegistration(fileName: string, key: string, factory: ts.Expression): ts.Statement {
return ts.createExpressionStatement(
ts.createCall(
ts.createPropertyAccess(
this._mockRepositoryAccess(fileName),
ts.createIdentifier('registerFactory'),
),
[],
[ts.createStringLiteral(key), factory],
this._getCallRegisterMock(fileName, key, factory)
);
}

private _getCallRegisterMock(fileName: string, key: string, factory: ts.Expression): ts.CallExpression {
return ts.createCall(
ts.createPropertyAccess(
this._mockRepositoryAccess(fileName),
ts.createIdentifier('registerFactory'),
),
[],
[ts.createStringLiteral(key), factory],
);
}

Expand Down
43 changes: 43 additions & 0 deletions test/registerMock/mockFromScope/mockFromScope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createMock, registerMock } from 'ts-auto-mock';

describe('registerMock using vars from the scope', () => {
it('should override standard behaviour of mock creation using values from the scope', () => {
interface APropInterface {
internalProp: string;
call: () => APropInterface;
}

interface AParentInterface {
prop: APropInterface;
}

const propInstance: APropInterface = { internalProp: 'whaaat', call: () => propInstance };

registerMock<APropInterface>(() => propInstance);

const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop).toBe(propInstance);
expect(mock.prop.call()).toBe(propInstance);
});

it('should override standard behaviour of mock creation using values from createMock', () => {
interface APropInterface {
internalProp: string;
call: () => APropInterface;
}

interface AParentInterface {
prop: APropInterface;
}

const propInstance: APropInterface = createMock<APropInterface>();

registerMock<APropInterface>(() => propInstance);

const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop).toBe(propInstance);
expect(mock.prop.call()).toBe(propInstance);
});
});

0 comments on commit b14bd5c

Please sign in to comment.