Skip to content

Commit

Permalink
feat(core): Support of standalone declarations #2687
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Jun 18, 2022
1 parent 3da91ce commit 797cec3
Show file tree
Hide file tree
Showing 54 changed files with 1,558 additions and 101 deletions.
1 change: 1 addition & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ exclude_patterns:
- 'karma.conf.ts'
- 'karma.ie.sh'
- 'renovate.json'
- 'webpack.config.js'
- '**/*.json'
- '**/*.md'
- '**/*.yml'
Expand Down
8 changes: 3 additions & 5 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,12 @@ overrides:
- single
- avoidEscape: true
allowTemplateLiterals: true
sort-imports:
- error
- ignoreCase: true
ignoreDeclarationSort: true
allowSeparatedGroups: true
import/order:
- error
- newlines-between: always
alphabetize:
order: asc
caseInsensitive: true
groups:
- builtin
- external
Expand Down
52 changes: 52 additions & 0 deletions docs/articles/api/MockBuilder.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ where **everything in the module will be replaced with their mocks**, except the
beforeEach(() => {
return MockBuilder(TheThing, ItsModule);
});

// To test a component
beforeEach(() => {
return MockBuilder(TheComponent, ItsModule);
});

// To test a directive
beforeEach(() => {
return MockBuilder(TheDirective, ItsModule);
});

// To test a pipe
beforeEach(() => {
return MockBuilder(ThePipe, ItsModule);
});

// To test a standalone declarations
beforeEach(() => {
return MockBuilder(TheStandaloneDeclaration).mock(OneOfItsImports);
});
```

`MockBuilder` tends to provide **a simple instrument to turn Angular dependencies into their mocks**,
Expand All @@ -26,6 +46,7 @@ and has a rich toolkit that supports:
- detection and creation of mocks for root providers
- replacement of modules and declarations at any depth
- exclusion of modules, declarations and providers at any depth
- shallow testing of [standalone declarations](#shallow-flag)

## Simple example

Expand Down Expand Up @@ -375,6 +396,30 @@ beforeEach(() => {
});
```

### `shallow` flag

The `shallow` flag works with kept standalone declarations.
It signals `MockBuilder` to mock all imports of the declaration, whereas the declaration itself won't be mocked.

```ts
beforeEach(() => {
return MockBuilder()
.keep(StandaloneComponent, {
shallow: true, // all imports of StandaloneComponent will be mocks.
});
});
```

Also, if a standalone declaration has been passed as the first parameter of `MockBuilder`,
then the `shallow` flag will be automatically set. It allows smooth shallow testing of them.

```ts
beforeEach(() => {
// All imports, apart from OneOfItsDependenciesPipe, of StandaloneComponent will be mocks.
return MockBuilder(StandaloneComponent).keep(OneOfItsDependenciesPipe);
});
```

### `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 @@ -474,6 +519,13 @@ All other root providers will be replaced with their mocks, even for kept declar

## Factory function

You might be using other [testing frameworks for angular](../extra/with-3rd-party),
such as `@ngneat/spectator` or `@testing-library/angular`.

This is a use-case for the factory function.

The factory function allows you to get a preconfigured `TestBed` declarations which can be passed wherever else.

```ts
const ngModule = MockBuilder(MyComponent, MyModule)
.build();
Expand Down
26 changes: 26 additions & 0 deletions docs/articles/api/MockComponent.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The class of a mock component has:
- support for `@ContentChild` and `@ContentChildren`
- support for `ControlValueAccessor`, `Validator` and `AsyncValidator`
- support for `exportAs`
- support for [standalone components](#standalone-components)

:::tip
Information about mocking FormControl, ControlValueAccessor, Validator and AsyncValidator
Expand Down Expand Up @@ -84,6 +85,7 @@ and [`MockRender`](MockRender.md):
```ts
describe('Test', () => {
beforeEach(() => {
// DependencyComponent is a declaration or imported somewhere in ItsModule.
return MockBuilder(TargetComponent, ItsModule);
});

Expand All @@ -94,6 +96,30 @@ describe('Test', () => {
});
```

## Standalone components

Starting Angular 14, it provides support for standalone components.
They are supported by `ng-mocks`. To mock a standalone component, you need to call `MockComponent` in imports:

```ts
TestBed.configureTestingModule({
imports: [
// for a single component
MockComponent(StandaloneComponent),

// for a set of components
...MockComponents(Standalone1Component, Standalone2Component),
],
declarations: [
// our component for testing
TargetComponent,
],
});
```

[`MockBuilder`](./MockBuilder.md) also supports standalone components
and allows to mock their imports only for shallow rendering.

## Advanced example

An advanced example about **mocking components**.
Expand Down
28 changes: 27 additions & 1 deletion docs/articles/api/MockDirective.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ A mock directive has:
- support for `@ContentChild` and `@ContentChildren`
- support for `ControlValueAccessor`, `Validator` and `AsyncValidator`
- supports `exportAs`
- support for [standalone directives](#standalone-directives)

:::tip
Information about mocking FormControl, ControlValueAccessor, Validator and AsyncValidator
Expand Down Expand Up @@ -84,7 +85,7 @@ and [`MockRender`](MockRender.md):
```ts
describe('Test', () => {
beforeEach(() => {
// DependencyDirective is a declaration in ItsModule.
// DependencyDirective is a declaration or imported somewhere in ItsModule.
return MockBuilder(TargetComponent, ItsModule);
});

Expand All @@ -95,6 +96,31 @@ describe('Test', () => {
});
```

## Standalone directives

Angular 14 has introduced support for standalone directives.
`ng-mocks` recognizes and properly mocks them.
To mock a standalone directive, you need to call `MockDirective` in imports:

```ts
TestBed.configureTestingModule({
imports: [
// for a single directive
MockDirective(StandaloneDirective),

// for a set of directives
...MockDirectives(Standalone1Directive, Standalone2Directive),
],
declarations: [
// our component for testing
TargetComponent,
],
});
```

[`MockBuilder`](./MockBuilder.md) recognizes and handles standalone directives.
Also, it allows to mock their imports only for shallow testing.

## Advanced example with attribute directives

An advanced example about **mocking attribute directives**.
Expand Down
22 changes: 22 additions & 0 deletions docs/articles/api/MockPipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ A mock pipe has:

- the same `name`
- default transform is `() => undefined` to prevent problems with chaining
- support for [standalone pipes](#standalone-pipes)

## Simple example

Expand Down Expand Up @@ -96,6 +97,27 @@ describe('Test', () => {
});
```

## Standalone pipes

Since Angular 14, pipes can be implemented as a standalone declaration.
`ng-mocks` detects and correctly mocks them.
To mock a standalone pipe, you need to call `MockPipe` in imports:

```ts
TestBed.configureTestingModule({
imports: [
// for a single pipe
MockPipe(StandalonePipe),
],
declarations: [
// our component for testing
TargetComponent,
],
});
```

[`MockBuilder`](./MockBuilder.md) also supports and correctly works with standalone pipes.

## Advanced example

An advanced example of **mocking pipes** in Angular tests.
Expand Down
11 changes: 10 additions & 1 deletion docs/articles/api/ngMocks/get.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ title: ngMocks.get
description: Documentation about ngMocks.get from ng-mocks library
---

Returns an attribute or structural directive which belongs to the current element.
Returns a declaration, service or token, which can be attribute or structural directives,
which belongs to the current element.

- `ngMocks.get( debugElement, directive, notFoundValue? )`

Expand All @@ -16,3 +17,11 @@ or simply with selectors which are supported by [`ngMocks.find`](./find.md).
```ts
const directive = ngMocks.get('app-component', Directive);
```

## Root providers

If you need to get a root provider, then `ngMocks.get` should be called without the first parameter:

```ts
const appId = ngMocks.get(APP_ID);
```
Loading

0 comments on commit 797cec3

Please sign in to comment.