Skip to content

Commit

Permalink
feat: now .mock extends by default, use precise flag to get old b…
Browse files Browse the repository at this point in the history
…ehavior
  • Loading branch information
satanTime committed Dec 1, 2020
1 parent 2e8f5cf commit bf576fd
Show file tree
Hide file tree
Showing 20 changed files with 887 additions and 77 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,7 @@ and has a rich toolkit that supports:
* [`.exclude()`](#mockbuilderexclude)
* [`.replace()`](#mockbuilderreplace)
* [`.provide()`](#mockbuilderprovide)
* [`precise` flag](#mockbuilder-precise-flag)
* [`export` flag](#mockbuilder-export-flag)
* [`exportAll` flag](#mockbuilder-exportall-flag)
* [`dependency` flag](#mockbuilder-dependency-flag)
Expand Down Expand Up @@ -1802,6 +1803,37 @@ beforeEach(() => {
});
```

#### MockBuilder `precise` flag

By default, when [`.mock(MyService, mock)`](#mockbuildermock) is used it creates a mock copy via
[`MockService(MyService, mock)`](#how-to-create-a-mock-service).
In some cases we might want to use the exactly passed mock object instead of that.
For this behavior we need to set `precise` flag to `true`.

```typescript
declare class MyService {
p1: boolean;
getP1(): boolean;
}
const mock = {
p1: true,
};

beforeEach(() => {
return (
MockBuilder(MyComponent, MyModule)
// its instance !== mock, but instance.p1 === mock.p1
// instance.getP1() returns undefined
.mock(MyService, mock)
// its intance === mock, therefore instance.p1 === mock.p1
// and instance.getP1 does not exist.
.mock(MyService, mock, {
precise: true,
})
);
});
```

#### MockBuilder `export` flag

If we want to test a component, directive or pipe which, unfortunately, has not been exported,
Expand Down
46 changes: 23 additions & 23 deletions lib/mock-builder/mock-builder.performance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,20 +660,20 @@ describe('MockBuilderPerformance', () => {
it('accepts the same render configDef', () => {
const render = {};
const ngModule1 = MockBuilder()
.keep(Target1Module, { render })
.mock(Target1Module, { render })
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, { render })
.mock(Target1Module, { render })
.build();

expect(ngModule1.providers?.[0]).toBe(ngModule2.providers?.[0]);
});
it('fails on different render flag configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, { render: true })
.mock(Target1Module, { render: true })
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, { render: false })
.mock(Target1Module, { render: false })
.build();

expect(ngModule1.providers?.[0]).not.toBe(
Expand All @@ -682,10 +682,10 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different render length configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, { render: {} })
.mock(Target1Module, { render: {} })
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {},
},
Expand All @@ -698,14 +698,14 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different render.$implicit configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
$implicit: true,
},
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
$implicit: false,
},
Expand All @@ -719,14 +719,14 @@ describe('MockBuilderPerformance', () => {
it('accepts the same render.variables configDef', () => {
const variables = {};
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables,
},
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables,
},
Expand All @@ -737,7 +737,7 @@ describe('MockBuilderPerformance', () => {
});
it('accepts equal render.variables configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 1,
Expand All @@ -746,7 +746,7 @@ describe('MockBuilderPerformance', () => {
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 1,
Expand All @@ -759,10 +759,10 @@ describe('MockBuilderPerformance', () => {
});
it('fails on missed definition configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, { render: {} })
.mock(Target1Module, { render: {} })
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 2,
Expand All @@ -771,7 +771,7 @@ describe('MockBuilderPerformance', () => {
})
.build();
const ngModule3 = MockBuilder()
.keep(Target1Module, { render: {} })
.mock(Target1Module, { render: {} })
.build();

expect(ngModule1.providers?.[0]).not.toBe(
Expand All @@ -783,7 +783,7 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different render.variables configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 1,
Expand All @@ -792,7 +792,7 @@ describe('MockBuilderPerformance', () => {
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 1,
Expand All @@ -808,7 +808,7 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different values in render.variables configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 1,
Expand All @@ -817,7 +817,7 @@ describe('MockBuilderPerformance', () => {
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
variables: {
flag: 2,
Expand All @@ -832,14 +832,14 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different amount of blocks in render configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
block1: {},
},
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
block1: {},
block2: {},
Expand All @@ -853,7 +853,7 @@ describe('MockBuilderPerformance', () => {
});
it('fails on different block definitions in render configDef', () => {
const ngModule1 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
block1: {
$implicit: true,
Expand All @@ -862,7 +862,7 @@ describe('MockBuilderPerformance', () => {
})
.build();
const ngModule2 = MockBuilder()
.keep(Target1Module, {
.mock(Target1Module, {
render: {
block1: {
$implicit: false,
Expand Down
2 changes: 1 addition & 1 deletion lib/mock-builder/mock-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const resetTestingModule = (
* @see https://github.com/ike18t/ng-mocks#mockbuilder
*/
export function MockBuilder(
keepDeclaration?: AnyType<any> | InjectionToken<any> | null | undefined,
keepDeclaration?: string | AnyType<any> | InjectionToken<any> | null | undefined,
itsModuleToMock?: AnyType<any> | null | undefined,
): IMockBuilder {
if (!(TestBed as any).ngMocks) {
Expand Down
13 changes: 9 additions & 4 deletions lib/mock-builder/promise/try-mock-provider.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { isNgDef } from '../../common/func.is-ng-def';
import ngMocksUniverse from '../../common/ng-mocks-universe';
import { ngMocks } from '../../mock-helper/mock-helper';
import helperMockService from '../../mock-service/helper.mock-service';
import mockProvider from '../../mock-service/mock-provider';
import { MockService } from '../../mock-service/mock-service';
import { IMockBuilderConfigMock } from '../types';

const createInstance = (def: any, instance: any, config: IMockBuilderConfigMock, isFunc: boolean): any => {
const params = isFunc ? { transform: instance } : instance;

return config.precise ? instance : MockService(def, params);
};

export default (def: any, defValue: Map<any, any>): void => {
if (isNgDef(def, 'i') && defValue.has(def)) {
const config: IMockBuilderConfigMock = ngMocksUniverse.config.get(def) || {};
const instance = defValue.get(def);
const isFunc = isNgDef(def, 'p') && typeof instance === 'function';
ngMocksUniverse.builtProviders.set(
def,
helperMockService.useFactory(def, () =>
isFunc ? ngMocks.stub(MockService(def), { transform: instance }) : instance,
),
helperMockService.useFactory(def, () => createInstance(def, instance, config, isFunc)),
);
} else if (isNgDef(def, 'i')) {
ngMocksUniverse.builtProviders.set(def, mockProvider(def));
Expand Down
67 changes: 23 additions & 44 deletions lib/mock-builder/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { InjectionToken, NgModule, PipeTransform, Provider } from '@angular/core';
import { TestBed } from '@angular/core/testing';

import { AnyType, Type } from '../common/core.types';
import { NgModuleWithProviders } from '../common/func.is-ng-module-def-with-providers';
import { AnyType } from '../common/core.types';

export interface IMockBuilderResult {
testBed: typeof TestBed;
Expand Down Expand Up @@ -52,6 +51,13 @@ export interface IMockBuilderConfigDirective {
};
}

export interface IMockBuilderConfigMock {
/**
* @see https://github.com/ike18t/ng-mocks#mockbuilder-precise-flag
*/
precise?: boolean;
}

export type IMockBuilderConfig =
| IMockBuilderConfigAll
| IMockBuilderConfigModule
Expand All @@ -74,52 +80,31 @@ export interface IMockBuilder extends Promise<IMockBuilderResult> {
/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderkeep
*/
keep<T>(def: NgModuleWithProviders<T>, config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderkeep
*/
keep<T>(token: InjectionToken<T>, config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderkeep
*/
keep<T>(def: AnyType<T>, config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderkeep
*/
keep(def: any, config?: IMockBuilderConfig): this;
keep(def: any, config?: IMockBuilderConfigAll & IMockBuilderConfigModule): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T extends PipeTransform>(pipe: AnyType<T>, config?: IMockBuilderConfig): this;
mock<T extends PipeTransform>(pipe: AnyType<T>, mock: T['transform'], config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T extends PipeTransform>(pipe: AnyType<T>, mock?: PipeTransform['transform'], config?: IMockBuilderConfig): this;
mock<T = any>(provider: string, mock: T, config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(token: InjectionToken<T>, mock: any, config: IMockBuilderConfig): this;
mock<T>(token: InjectionToken<T>, mock: InjectionToken<T> | T | undefined, config?: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(provider: AnyType<T>, mock: AnyType<T> | Partial<T>, config: IMockBuilderConfig): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(token: InjectionToken<T>, mock?: any): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(def: NgModuleWithProviders<T>): this;
mock<T>(
provider: AnyType<T>,
mock: AnyType<T> | Partial<T>,
config?: IMockBuilderConfig & IMockBuilderConfigMock,
): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
Expand All @@ -129,17 +114,7 @@ export interface IMockBuilder extends Promise<IMockBuilderResult> {
/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(provider: AnyType<T>, mock?: Partial<T>): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock<T>(def: AnyType<T>): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuildermock
*/
mock(input: any, a1: any, a2?: any): this;
mock(def: any): this;

/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderprovide
Expand All @@ -149,5 +124,9 @@ export interface IMockBuilder extends Promise<IMockBuilderResult> {
/**
* @see https://github.com/ike18t/ng-mocks#mockbuilderreplace
*/
replace(source: Type<any>, destination: Type<any>, config?: IMockBuilderConfig): this;
replace(
source: AnyType<any>,
destination: AnyType<any>,
config?: IMockBuilderConfigAll & IMockBuilderConfigModule,
): this;
}

0 comments on commit bf576fd

Please sign in to comment.