Skip to content

Commit

Permalink
Merge pull request #2396 from satanTime/issues/2362
Browse files Browse the repository at this point in the history
docs(MockRender): better info about fixture and point #2362
  • Loading branch information
satanTime authored May 7, 2022
2 parents 44cad53 + a06a429 commit c21822b
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 71 deletions.
46 changes: 31 additions & 15 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,16 @@ jobs:
- checkout
- restore_cache:
key: root-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "package-lock.json" }}
- restore_cache:
key: docs-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "docs/package-lock.json" }}
- run:
name: NPM Install
command: |
if [ ! -d "./node_modules/" ]; then
npm ci --no-optional
fi
if [ ! -d "./docs/node_modules/" ]; then
cd docs && npm ci --no-optional && cd ..
fi
- save_cache:
key: root-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- save_cache:
key: docs-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "docs/package-lock.json" }}
paths:
- ./docs/node_modules
- run:
name: Prettier
command: npm run prettier:check
Expand Down Expand Up @@ -60,9 +51,6 @@ jobs:
- run:
name: Unit Tests
command: WITH_COVERAGE=1 npm run test
- run:
name: Docs
command: npm run build:docs
- store_test_results:
path: ./test-reports
- store_artifacts:
Expand Down Expand Up @@ -119,6 +107,27 @@ jobs:
- run:
name: E2E
command: npm run e2e
'Docs':
docker:
- image: satantime/puppeteer-node:16.15.0
resource_class: medium
steps:
- checkout
- restore_cache:
key: docs-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "docs/package-lock.json" }}
- run:
name: NPM Install
command: |
if [ ! -d "./docs/node_modules/" ]; then
cd docs && npm ci --no-optional && cd ..
fi
- save_cache:
key: docs-<< pipeline.parameters.lockindex >>-{{ arch }}-{{ checksum "docs/package-lock.json" }}
paths:
- ./docs/node_modules
- run:
name: Docs
command: npm run build:docs
'Angular Jasmine Install':
docker:
- image: satantime/puppeteer-node:16.15.0
Expand Down Expand Up @@ -1575,9 +1584,13 @@ jobs:
condition:
or:
- not:
matches:
pattern: 'renovate/e2e/.*'
value: << pipeline.git.branch >>
and:
- matches:
pattern: 'renovate/e2e/.*'
value: << pipeline.git.branch >>
- matches:
pattern: 'docs/.*'
value: << pipeline.git.branch >>
- matches:
pattern: 'renovate/e2e/a5/.*'
value: << pipeline.git.branch >>
Expand Down Expand Up @@ -1640,6 +1653,9 @@ workflows:
- 'Performance':
requires:
- Core
- 'Docs':
requires:
- Core
- 'Angular Jasmine Install':
requires:
- Core
Expand Down
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,6 @@ An example of a spec for a profile edit component.
// In the following test suite, we would like to
// cover behavior of the component.
describe('profile:classic', () => {
// First of all, we would like to reuse the same
// TestBed in every test.
// ngMocks.faster suppresses reset of TestBed
// after each test and allows to use TestBed,
// MockBuilder and MockRender in beforeAll.
// https://ng-mocks.sudo.eu/api/ngMocks/faster
ngMocks.faster();

// Helps to reset customizations after each test.
MockInstance.scope();

Expand Down
42 changes: 25 additions & 17 deletions docs/articles/api/MockRender.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: MockRender - shallow rendering in Angular tests
describe: Information about shallow rendering in Angular tests via MockRender from ng-mocks
title: MockRender - advanced rendering in Angular tests
describe: Information about rendering in Angular tests via MockRender from ng-mocks
sidebar_label: MockRender
---

**Shallow rendering in Angular tests** is provided via `MockRender` function.
`MockRender` helps when we want to assert `Inputs`, `Outputs`, `ChildContent`, or to render custom templates.
**Advanced rendering in Angular tests** is provided via `MockRender` function.
`MockRender` helps when you want to assert `Inputs`, `Outputs`, `ChildContent`, or to render custom templates.

`MockRender` uses Angular `TestBed.createComponent` under the hood and provides:

- shallow rendering of Components, Directives, Services, Tokens
- correct bindings to `Inputs` and `Outputs`
- rendering of custom templates
- support for all lifecycle hooks (`ngOnInit`, `ngOnChanges` etc)
- support for testing `ChangeDetectionStrategy.OnPush` components
Expand All @@ -35,13 +35,17 @@ and **supports not only components, but also directives, services and tokens**.

### Proxy between params and fixture

When `MockRender(Component, params)` is used then `fixture.componentInstance` is a proxy to existing keys in `params`,
There are `fixture.componentInstance` and `fixture.point.componentInstance` with `MockRender` usage,
and, it's important to know their difference:

- `fixture.point.componentInstance` is the real component instance
- `fixture.componentInstance` correctly controls `@Inputs` and `@Outputs` of the component

When `MockRender(Component, params)` is used then `fixture.componentInstance` is a proxy to the `params`,
therefore, changing `fixture.componentInstance` is the same as changing `params` and vise-versa.

The same happens with `fixture.componentInstance` and `fixture.point.componentInstance`.
If `params` don't have a property which exists in `fixture.point.componentInstance`,
then changing this property via `fixture.componentInstance`
will change it in `fixture.point.componentInstance` and vise-versa.
When `MockRender(Component)` is used without params then `fixture.componentInstance` controls `@Inputs` and `@Outputs`
of the component. That let trigger correct lifecycle hooks.

An example:

Expand Down Expand Up @@ -73,7 +77,8 @@ fixture.componentInstance.i1 = 7;

params.i2 = 8;
// It does nothing, because the proxy is based on
// the initial keys of params.
// the initial keys of params,
// and i2 isn't present there.

fixture.point.componentInstance.i2 = 3;
// Now fixture.componentInstance.i2 = 3.
Expand All @@ -83,13 +88,16 @@ fixture.componentInstance.i2 = 4;

fixture.point.componentInstance.i3 = 5;
// It does nothing, because the proxy is based on
// the initial properties in the point.
// the initial properties in the point,
// and i3 isn't present there.
```

Looks too complicated, right?

That's why the best way to write tests with `MockRender` is to rely on `params` and `fixture.point` only
and to avoid usage of `fixture.componentInstance`.
That's why the best way to write tests with `MockRender` is to rely on

- `fixture.componentInstance` or `params` if you want to change inputs / outputs
- `fixture.point.componentInstance` if you want to assert expectations

:::tip
As a possible solution, `params` might be spread:
Expand All @@ -102,16 +110,16 @@ const fixture = MockRender(Component, { ...params });
### One MockRender per one test

`MockRender` creates a special wrapper component which should be injected into `TestBed`.
The component is needed in order to render a custom template, which is provided or generated based on parameters.
An injection of a component into `TestBed` is possible only if `TestBed` has not been used yet.
The wrapper is needed in order to render a custom template, which is provided or generated based on parameters.
A declaration of new components in `TestBed` is possible only if `TestBed` has not been used yet.

Because of this,
usage of `MockRender` after usage of `TestBed.get`, `TestBed.inject`, `TestBed.createComponent` or another `MockRender`
triggers an error about dirty `TestBed`.

However, it is still possible to use `MockRender` more than once in a test.
It requires a reset of `TestBed` (check [`ngMocks.flushTestBed`](./ngMocks/flushTestBed.md)).
Please pay attention, that this makes all existing service instances obsolete.
Please note, that this makes all existing service instances obsolete.

```ts
it('two renders', () => {
Expand Down
8 changes: 0 additions & 8 deletions docs/articles/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,6 @@ An example of a spec for a profile edit component.
// In the following test suite, we would like to
// cover behavior of the component.
describe('profile:classic', () => {
// First of all, we would like to reuse the same
// TestBed in every test.
// ngMocks.faster suppresses reset of TestBed
// after each test and allows to use TestBed,
// MockBuilder and MockRender in beforeAll.
// https://ng-mocks.sudo.eu/api/ngMocks/faster
ngMocks.faster();

// Helps to reset customizations after each test.
MockInstance.scope();

Expand Down
10 changes: 1 addition & 9 deletions examples/readme/classic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,12 @@ const assertion: any =
// In the following test suite, we would like to
// cover behavior of the component.
describe('profile:classic', () => {
// First of all, we would like to reuse the same
// TestBed in every test.
// ngMocks.faster suppresses reset of TestBed
// after each test and allows to use TestBed,
// MockBuilder and MockRender in beforeAll.
// https://ng-mocks.sudo.eu/api/ngMocks/faster
ngMocks.faster();

// Helps to reset customizations after each test.
MockInstance.scope();

// Let's declare TestBed in beforeAll instead of beforeEach.
// The code mocks everything in SharedModule and provides a mock AuthService.
beforeAll(async () => {
beforeEach(async () => {
return TestBed.configureTestingModule({
imports: [
MockModule(SharedModule), // mock
Expand Down
22 changes: 8 additions & 14 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@
"enabled": false
},

{
"packagePatterns": ["^@docusaurus/"],
"allowedVersions": "/^\\d+\\.\\d+\\.\\d+(-[^\\.]+\\.\\d+)?$/",
"ignoreUnstable": false
},

{
"packagePatterns": ["satantime/puppeteer-node"],
"major": {
Expand All @@ -43,17 +37,17 @@
},

{
"paths": [
".circleci/config.yml",
"Dockerfile",
"docker-compose.yml",
"docs/package.json",
"tests-e2e/package.json",
"package.json"
],
"paths": [".circleci/config.yml", "Dockerfile", "docker-compose.yml", "tests-e2e/package.json", "package.json"],
"additionalBranchPrefix": "root/"
},

{
"paths": ["docs/package.json"],
"additionalBranchPrefix": "docs/",
"allowedVersions": "/.+/",
"ignoreUnstable": false
},

{
"paths": ["e2e/a-jasmine/package.json"],
"additionalBranchPrefix": "e2e/jasmine/",
Expand Down

0 comments on commit c21822b

Please sign in to comment.