Skip to content

Commit

Permalink
feat(ngMocks.defaultConfig): config for MockBuilder #971
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Mar 19, 2022
1 parent 1d8fc02 commit 9415f57
Show file tree
Hide file tree
Showing 17 changed files with 473 additions and 26 deletions.
35 changes: 22 additions & 13 deletions docs/articles/api/MockBuilder.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ beforeEach(() => {
});
```

## .keep()
## Chain functions

### .keep()

If we want to keep a module, component, directive, pipe or provider as it is. We should use `.keep`.

Expand All @@ -119,7 +121,7 @@ beforeEach(() => {
});
```

## .mock()
### .mock()

If we want to turn anything into a mock object, even a part of a kept module we should use `.mock`.

Expand Down Expand Up @@ -157,7 +159,7 @@ beforeEach(() => {
});
```

## .exclude()
### .exclude()

If we want to exclude something, even a part of a kept module we should use `.exclude`.

Expand All @@ -173,7 +175,7 @@ beforeEach(() => {
});
```

## .replace()
### .replace()

If we want to replace something with something, we should use `.replace`.
The replacement has to be decorated with the same decorator as the source.
Expand Down Expand Up @@ -208,7 +210,7 @@ beforeEach(() => {
});
```

## .provide()
### .provide()

If we want to add or replace providers / services, we should use `.provide`. It has the same interface as a regular provider.

Expand All @@ -222,7 +224,12 @@ beforeEach(() => {
});
```

## `precise` flag
## Config

You can customize default behavior of mock things.
Also, it can be done globally via [`ngMocks.defaultConfig()`](./ngMocks/defaultConfig.md) to avoid repetitions.

### `precise` flag

By default, when [`.mock(Service, mock)`](#mock) is used it creates a mock object via
[`MockService(Service, mock)`](MockService.md).
Expand Down Expand Up @@ -253,7 +260,7 @@ beforeEach(() => {
});
```

## `export` flag
### `export` flag

If we want to test a component, directive or pipe which, unfortunately, has not been exported,
then we need to mark it with the `export` flag.
Expand All @@ -271,7 +278,7 @@ beforeEach(() => {
});
```

## `exportAll` flag
### `exportAll` flag

If we want to use all the declarations of a module which have not been exported,
we need to mark the module with the `exportAll` flag. Then all its imports and declarations will be exported.
Expand All @@ -290,7 +297,7 @@ beforeEach(() => {
});
```

## `dependency` flag
### `dependency` flag

By default, all definitions are added to the `TestingModule` if they are not a dependency of another definition.
Modules are added as imports to the `TestingModule`.
Expand Down Expand Up @@ -324,7 +331,7 @@ beforeEach(() => {
});
```

## `render` flag
### `render` flag

When we want to render a structural directive by default, we can do that via adding the `render` flag in its config.

Expand Down Expand Up @@ -365,7 +372,9 @@ beforeEach(() => {
});
```

## `NG_MOCKS_GUARDS` token
## Tokens

### `NG_MOCKS_GUARDS` token

If we want to test guards, we need to [`.keep`](#keep) them, but what should we do with other guards we do not want to care about at all?
The answer is to exclude `NG_MOCKS_GUARDS` token, it will **remove all the guards** from routes except the explicitly configured ones.
Expand All @@ -377,7 +386,7 @@ beforeEach(() => {
});
```

## `NG_MOCKS_INTERCEPTORS` token
### `NG_MOCKS_INTERCEPTORS` token

Usually, when we want to test an interceptor, we want to avoid influences of other interceptors.
To **remove all interceptors in an angular test** we need to exclude `NG_MOCKS_INTERCEPTORS` token,
Expand All @@ -390,7 +399,7 @@ beforeEach(() => {
});
```

## `NG_MOCKS_ROOT_PROVIDERS` token
### `NG_MOCKS_ROOT_PROVIDERS` token

There are root services and tokens apart from provided ones in Angular applications.
It might happen that in a test we want these providers to be replaced with their mocks or to be kept.
Expand Down
42 changes: 42 additions & 0 deletions docs/articles/api/ngMocks/defaultConfig.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: ngMocks.defaultConfig
description: Documentation about ngMocks.defaultConfig from ng-mocks library
---

Sets default config for mocks in [`MockBuilder`](../MockBuilder.md#config).

- `ngMocks.defaultConfig( Component, config )` - sets a default config for a component
- `ngMocks.defaultConfig( Directive, config )` - sets a default config for a directive
- `ngMocks.defaultConfig( Component )` - removes config
- `ngMocks.defaultConfig( Directive )` - removes config

The best place to do that is in `src/test.ts` for jasmine or in `src/setup-jest.ts` / `src/test-setup.ts` for `jest`.

For example, if you have a simple structural directive which you always want to render it.
Then, you can configure it via `ngMocks.defaultConfig`.

```ts title="src/test.ts"
// Config for a structural directive.
ngMocks.defaultConfig(StructuralDirective, {
// render the mock of the directive by default
render: true,
});

// Config for a component with content views.
ngMocks.defaultConfig(ViewComponent, {
render: {
// render a block by default
block1: true,

// render a block with context
block2: {
$implicit: {
data: 'MOCK_DATA',
},
},
},
});

// removing the config.
ngMocks.defaultMock(StructuralDirective);
```
1 change: 1 addition & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module.exports = {
label: 'ngMocks',
items: [
'api/ngMocks',
'api/ngMocks/defaultConfig',
'api/ngMocks/defaultMock',
'api/ngMocks/globalExclude',
'api/ngMocks/globalKeep',
Expand Down
12 changes: 11 additions & 1 deletion libs/ng-mocks/src/lib/common/decorate.mock.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import coreDefineProperty from './core.define-property';
import { AnyType } from './core.types';
import { ngMocksMockConfig } from './mock';
import ngMocksUniverse from './ng-mocks-universe';

export default function (mock: AnyType<any>, source: AnyType<any>, config: ngMocksMockConfig = {}): void {
export default function (mock: AnyType<any>, source: AnyType<any>, configInput: ngMocksMockConfig = {}): void {
coreDefineProperty(mock, 'mockOf', source);
coreDefineProperty(mock, 'nameConstructor', mock.name);
coreDefineProperty(mock, 'name', `MockOf${source.name}`, true);
const config = ngMocksUniverse.getConfigMock().has(source)
? {
...configInput,
config: {
...ngMocksUniverse.getConfigMock().get(source),
...configInput.config,
},
}
: configInput;
coreDefineProperty(mock.prototype, '__ngMocksConfig', config);
}
4 changes: 4 additions & 0 deletions libs/ng-mocks/src/lib/common/ng-mocks-universe.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { InjectionToken } from '@angular/core';

import { IMockBuilderConfig } from '../mock-builder/types';

import coreConfig from './core.config';
import { AnyType } from './core.types';

Expand All @@ -23,6 +25,7 @@ interface NgMocksUniverse {
configInstance: Map<any, any>;
flags: Set<string>;
getBuildDeclaration: (def: any) => any | undefined;
getConfigMock: () => Map<any, IMockBuilderConfig>;
getDefaults: () => Map<any, ['mock' | 'keep' | 'replace' | 'exclude', any?]>;
getLocalMocks: () => Array<[any, any]>;
getOverrides: () => Map<any, any>;
Expand Down Expand Up @@ -56,6 +59,7 @@ ngMocksUniverse.global.set('flags', {

ngMocksUniverse.getOverrides = globalMap('overrides');
ngMocksUniverse.getDefaults = globalMap('defaults');
ngMocksUniverse.getConfigMock = globalMap('configMock');

const getDefaults = (def: any): [] | ['mock' | 'keep' | 'replace' | 'exclude', any?] => {
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { NgModule } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';

import ngMocksUniverse from '../common/ng-mocks-universe';

Expand All @@ -15,7 +14,7 @@ import requiredMetadata from './performance/required-metadata';
import { IMockBuilderResult } from './types';

export class MockBuilderPerformance extends MockBuilderPromise {
public build(): NgModule {
public build(): TestModuleMetadata {
const global = ngMocksUniverse.global;

// avoiding influences on cache when users extend the testing module.
Expand Down
6 changes: 3 additions & 3 deletions libs/ng-mocks/src/lib/mock-builder/mock-builder.promise.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgModule, Provider } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Provider } from '@angular/core';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';

import { flatten, mapValues } from '../common/core.helpers';
import { Type } from '../common/core.types';
Expand Down Expand Up @@ -70,7 +70,7 @@ export class MockBuilderPromise implements IMockBuilder {
return this;
}

public build(): NgModule {
public build(): TestModuleMetadata {
this.stash.backup();
ngMocksUniverse.config.set('mockNgDefResolver', new Map());

Expand Down
5 changes: 4 additions & 1 deletion libs/ng-mocks/src/lib/mock-builder/promise/init-universe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export default ({
// flags to understand how to mock nested declarations.
ngMocksUniverse.config.set('ngMocksDepsResolution', new Map());
for (const [k, v] of mapEntries(configDef)) {
ngMocksUniverse.config.set(k, v);
ngMocksUniverse.config.set(k, {
...ngMocksUniverse.getConfigMock().get(k),
...v,
});
}
initKeepDef(keepDef);
initReplaceDef(replaceDef, defValue);
Expand Down
6 changes: 3 additions & 3 deletions libs/ng-mocks/src/lib/mock-builder/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InjectionToken, NgModule, PipeTransform, Provider } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { InjectionToken, PipeTransform, Provider } from '@angular/core';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';

import { AnyType } from '../common/core.types';

Expand Down Expand Up @@ -70,7 +70,7 @@ export interface IMockBuilder extends Promise<IMockBuilderResult> {
/**
* @see https://ng-mocks.sudo.eu/api/MockBuilder#factory-function
*/
build(): NgModule;
build(): TestModuleMetadata;

/**
* @see https://ng-mocks.sudo.eu/api/MockBuilder#exclude
Expand Down
20 changes: 20 additions & 0 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.default-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { InjectionToken } from '@angular/core';

import { flatten } from '../common/core.helpers';
import { AnyType } from '../common/core.types';
import ngMocksUniverse from '../common/ng-mocks-universe';
import { IMockBuilderConfig } from '../mock-builder/types';

export default <T>(
def: AnyType<T> | InjectionToken<T> | string | Array<AnyType<T> | InjectionToken<T> | string>,
config?: IMockBuilderConfig,
): void => {
const map = ngMocksUniverse.getConfigMock();
for (const item of flatten(def)) {
if (config) {
map.set(item, config);
} else {
map.delete(item);
}
}
};
2 changes: 2 additions & 0 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import mockHelperFormatText from './format/mock-helper.format-text';
import mockHelperAutoSpy from './mock-helper.auto-spy';
import mockHelperConsoleIgnore from './mock-helper.console-ignore';
import mockHelperConsoleThrow from './mock-helper.console-throw';
import mockHelperDefaultConfig from './mock-helper.default-config';
import mockHelperDefaultMock from './mock-helper.default-mock';
import mockHelperFaster from './mock-helper.faster';
import mockHelperFlushTestBed from './mock-helper.flush-test-bed';
Expand Down Expand Up @@ -62,6 +63,7 @@ export default {
}
},
crawl: mockHelperCrawl,
defaultConfig: mockHelperDefaultConfig,
defaultMock: mockHelperDefaultMock,
event: mockHelperEvent,
faster: mockHelperFaster,
Expand Down
15 changes: 14 additions & 1 deletion libs/ng-mocks/src/lib/mock-helper/mock-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ComponentFixture, TestModuleMetadata } from '@angular/core/testing';

import { AnyType, DebugNodeSelector, Type } from '../common/core.types';
import { NgModuleWithProviders } from '../common/func.is-ng-module-def-with-providers';
import { IMockBuilderConfig } from '../mock-builder/types';
import { MockedDebugElement, MockedDebugNode } from '../mock-render/types';
import { CustomMockFunction, MockedFunction } from '../mock-service/types';

Expand Down Expand Up @@ -53,12 +54,18 @@ export const ngMocks: {
includeTextNodes?: boolean,
): void;

/**
* @see https://ng-mocks.sudo.eu/api/ngMocks/defaultConfig
*/
defaultConfig<T>(token: string | InjectionToken<T> | AnyType<T>, config?: IMockBuilderConfig): void;

/**
* @see https://ng-mocks.sudo.eu/api/ngMocks/defaultMock
*/
defaultMock<T>(
token: InjectionToken<T>,
handler?: (value: undefined | T, injector: Injector) => undefined | Partial<T>,
config?: IMockBuilderConfig,
): void;

/**
Expand All @@ -67,19 +74,25 @@ export const ngMocks: {
defaultMock<T = any>(
token: string,
handler?: (value: undefined | T, injector: Injector) => undefined | Partial<T>,
config?: IMockBuilderConfig,
): void;

/**
* @see https://ng-mocks.sudo.eu/api/ngMocks/defaultMock
*/
defaultMock<T>(def: AnyType<T>, handler?: (value: T, injector: Injector) => void | Partial<T>): void;
defaultMock<T>(
def: AnyType<T>,
handler?: (value: T, injector: Injector) => void | Partial<T>,
config?: IMockBuilderConfig,
): void;

/**
* @see https://ng-mocks.sudo.eu/api/ngMocks/defaultMock
*/
defaultMock<T = any>(
defs: Array<AnyType<T> | InjectionToken<T>>,
handler?: (value: undefined | T, injector: Injector) => undefined | Partial<T>,
config?: IMockBuilderConfig,
): void;

/**
Expand Down
Loading

0 comments on commit 9415f57

Please sign in to comment.