Skip to content

Commit

Permalink
fix: better default type of MockedComponentFixture
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Jun 14, 2020
1 parent b5b14e7 commit cca6994
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 7 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<MyComponent>`.
>
> You should use either:
> `MockedComponentFixture<MyComponent>` or
> `ComponentFixture<DefaultRenderComponent<MyComponent>>`.
>
> 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<ComponentToRender> = MockRender(ComponentToRender)`.

Expand Down
2 changes: 1 addition & 1 deletion karma.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module.exports = (config: any) => {

karmaTypescriptConfig: {
include: ['karma-test-shim.ts', 'lib/**/*', 'examples/**/*', 'tests/**/*'],
tsconfig: 'tsconfig.json',
tsconfig: 'tsconfig.spec.json',
},
});
};
4 changes: 2 additions & 2 deletions lib/mock-render/mock-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface IMockRenderOptions {
}

// tslint:disable-next-line:interface-name
export interface MockedComponentFixture<C = any, F = undefined> extends ComponentFixture<F> {
export interface MockedComponentFixture<C = any, F = DefaultRenderComponent<C>> extends ComponentFixture<F> {
point: MockedDebugElement<C>;
}

Expand Down Expand Up @@ -56,7 +56,7 @@ function MockRender<MComponent, TComponent extends { [key: string]: any }>(
// without params we shouldn't autocomplete any keys of any types.
function MockRender<MComponent extends Record<keyof any, any>>(
template: Type<MComponent>
): MockedComponentFixture<MComponent, DefaultRenderComponent<MComponent>>;
): MockedComponentFixture<MComponent>;

function MockRender<MComponent = any, TComponent extends { [key: string]: any } = { [key: string]: any }>(
template: string,
Expand Down
52 changes: 50 additions & 2 deletions tests/mock-render-mirrors-component/test.spec.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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<TargetComponent>
const fixture1: MockedComponentFixture<TargetComponent> = 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<DefaultRenderComponent<TargetComponent>> = 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<TargetComponent, Record<'input1' | 'input3', string>> = 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<Record<'input1' | 'input3', string>> = MockRender(TargetComponent, {
input1: '1',
input3: '3',
});
expect(fixture4).toBeDefined();
expect(fixture4.componentInstance.input3).toBe('3');
});
});
6 changes: 6 additions & 0 deletions tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"files": ["index.ts", "jasmine.ts", "jest.ts"],
"exclude": ["e2e"],
"include": ["**/*.spec.ts"]
}

0 comments on commit cca6994

Please sign in to comment.