From cca6994d5d1d304a7dab9dd51285d93f47c61860 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 14 Jun 2020 13:32:18 +0200 Subject: [PATCH] fix: better default type of MockedComponentFixture --- README.md | 13 ++++- karma.conf.ts | 2 +- lib/mock-render/mock-render.ts | 4 +- .../test.spec.ts | 52 ++++++++++++++++++- tsconfig.spec.json | 6 +++ 5 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 tsconfig.spec.json diff --git a/README.md b/README.md index 9bb2ce7f69..d94673ebcd 100644 --- a/README.md +++ b/README.md @@ -700,9 +700,18 @@ const ngModule = MockBuilder(MyComponent, MyModule) Provides a simple way to render anything for ease of testing directives, pipes, `@Inputs`, `@Outputs`, `@ContentChild` of a component, etc. +> Please note, that `MockRender(MyComponent)` is not assignable to `ComponentFixture`. +> +> You should use either: +> `MockedComponentFixture` or +> `ComponentFixture>`. +> +> It happens because `MockRender` generates an additional component to render the desired thing +> and its interface differs. + It returns a `fixture` of type `MockedComponentFixture` (it extends `ComponentFixture`) with a `point` property. -`fixture.componentInstance` belongs to the middle component for the render, that is quite useless, -when `fixture.point` points to the debugElement of the passed component. +`fixture.componentInstance` belongs to the middle component for the render, +when `fixture.point` points to the debugElement of the desired component. Its type: `let fixture: MockedComponentFixture = MockRender(ComponentToRender)`. diff --git a/karma.conf.ts b/karma.conf.ts index 2554288919..167f28d325 100644 --- a/karma.conf.ts +++ b/karma.conf.ts @@ -38,7 +38,7 @@ module.exports = (config: any) => { karmaTypescriptConfig: { include: ['karma-test-shim.ts', 'lib/**/*', 'examples/**/*', 'tests/**/*'], - tsconfig: 'tsconfig.json', + tsconfig: 'tsconfig.spec.json', }, }); }; diff --git a/lib/mock-render/mock-render.ts b/lib/mock-render/mock-render.ts index 3659b7032e..59ae45ce0f 100644 --- a/lib/mock-render/mock-render.ts +++ b/lib/mock-render/mock-render.ts @@ -24,7 +24,7 @@ export interface IMockRenderOptions { } // tslint:disable-next-line:interface-name -export interface MockedComponentFixture extends ComponentFixture { +export interface MockedComponentFixture> extends ComponentFixture { point: MockedDebugElement; } @@ -56,7 +56,7 @@ function MockRender( // without params we shouldn't autocomplete any keys of any types. function MockRender>( template: Type -): MockedComponentFixture>; +): MockedComponentFixture; function MockRender( template: string, diff --git a/tests/mock-render-mirrors-component/test.spec.ts b/tests/mock-render-mirrors-component/test.spec.ts index d829b895fc..0d0ba8e306 100644 --- a/tests/mock-render-mirrors-component/test.spec.ts +++ b/tests/mock-render-mirrors-component/test.spec.ts @@ -1,5 +1,6 @@ -import { Component, EventEmitter, Input, NgModule, Output } from '@angular/core'; -import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { ChangeDetectorRef, Component, EventEmitter, Input, NgModule, Output } from '@angular/core'; +import { ComponentFixture } from '@angular/core/testing'; +import { DefaultRenderComponent, MockBuilder, MockedComponentFixture, MockRender, ngMocks } from 'ng-mocks'; import { first } from 'rxjs/operators'; @Component({ @@ -23,7 +24,16 @@ export class TargetComponent { public var1 = ''; public var2 = ''; + // required for DefaultRenderComponent generation assertion. + protected readonly cdf: ChangeDetectorRef; + protected var3 = ''; + + constructor(cdf: ChangeDetectorRef) { + this.cdf = cdf; + } + public test(var2: string): void { + this.var3 = this.var2; this.var2 = var2; } } @@ -80,4 +90,42 @@ describe('mock-render-mirrors-component', () => { output2.triggerEventHandler('click', null); expect(updatedOutput2).toBe(true); }); + + it('correctly inherits types', () => { + // keeps the 2nd args as DefaultRenderComponent + const fixture1: MockedComponentFixture = MockRender(TargetComponent); + fixture1.componentInstance.input1 = '1'; + fixture1.detectChanges(); + expect(fixture1).toBeDefined(); + expect(fixture1.componentInstance.input1).toBe('1'); + expect(fixture1.point.componentInstance.input1).toBe('1'); + + // we have to provide DefaultRenderComponent in this case. + // the generated component isn't the same as the testing component. + const fixture2: ComponentFixture> = MockRender(TargetComponent); + fixture2.componentInstance.input1 = '1'; + fixture2.detectChanges(); + expect(fixture2).toBeDefined(); + expect(fixture2.componentInstance.input1).toBe('1'); + + // full declaration of the mocked fixture type. + const fixture3: MockedComponentFixture> = MockRender( + TargetComponent, + { + input1: '1', + input3: '3', + } + ); + expect(fixture3).toBeDefined(); + expect(fixture3.componentInstance.input3).toBe('3'); + expect(fixture3.point.componentInstance.input1).toBe('1'); + + // full declaration of the default fixture type. + const fixture4: ComponentFixture> = MockRender(TargetComponent, { + input1: '1', + input3: '3', + }); + expect(fixture4).toBeDefined(); + expect(fixture4.componentInstance.input3).toBe('3'); + }); }); diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000000..824600dfcd --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "files": ["index.ts", "jasmine.ts", "jest.ts"], + "exclude": ["e2e"], + "include": ["**/*.spec.ts"] +}