diff --git a/README.md b/README.md index 7beaa6dcb3..ae269b16f4 100644 --- a/README.md +++ b/README.md @@ -365,11 +365,14 @@ describe('MockModule', () => { Providers simple way to render anything, change `@Inputs` and `@Outputs` of testing component, directives etc. It returns `fixture` with a `point` property if a component class was passed. -The `fixture` belongs the middle component for the render, -when `fixture.point` points to the debug element of the testing component. +The `fixture` belongs to the middle component for the render, +when `fixture.point` points to the debugElement of the passed component. The best thing here is that `fixture.point.componentInstance` is typed to the component's class. +If you want you can set providers for the render passing them via the 3rd parameter. +It is useful if you want to mock system tokens / services such as APP_INITIALIZER, DOCUMENT etc. + ### Usage Example ```typescript @@ -494,6 +497,9 @@ Add the next code to `src/test.ts` if you want all mocked methods and functions ```typescript import 'ng-mocks/dist/jasmine'; + +// uncomment in case if you existing tests with spies. +// jasmine.getEnv().allowRespy(true); ``` In case of jest. diff --git a/karma-test-shim.ts b/karma-test-shim.ts index 7b1a22ce9a..54f4389dfb 100644 --- a/karma-test-shim.ts +++ b/karma-test-shim.ts @@ -7,4 +7,6 @@ import 'core-js/es7/reflect'; // tslint:disable-line import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +jasmine.getEnv().allowRespy(true); + getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/lib/mock-render/mock-render.fixtures.ts b/lib/mock-render/mock-render.fixtures.ts index b407a5f84d..c20c300edc 100644 --- a/lib/mock-render/mock-render.fixtures.ts +++ b/lib/mock-render/mock-render.fixtures.ts @@ -1,4 +1,5 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { Component, EventEmitter, Inject, Input, Output } from '@angular/core'; @Component({ selector: 'render-real-component', @@ -7,4 +8,11 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; export class RenderRealComponent { @Output() click = new EventEmitter<{}>(); @Input() content = ''; + + public readonly document: Document; + + constructor(@Inject(DOCUMENT) document: Document) { + this.document = document; + this.document.getElementById('test'); + } } diff --git a/lib/mock-render/mock-render.spec.ts b/lib/mock-render/mock-render.spec.ts index 35d0fe2bf2..5977a28c29 100644 --- a/lib/mock-render/mock-render.spec.ts +++ b/lib/mock-render/mock-render.spec.ts @@ -1,7 +1,10 @@ import createSpy = jasmine.createSpy; +import { DOCUMENT } from '@angular/common'; import { TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { MockService } from '../mock-service'; + import { MockRender } from './mock-render'; import { RenderRealComponent } from './mock-render.fixtures'; @@ -88,4 +91,22 @@ describe('MockRender', () => { const fixture = MockRender(RenderRealComponent); expect(fixture.point.componentInstance).toEqual(jasmine.any(RenderRealComponent)); }); + + it('returns pointer with a provided component', () => { + const document = MockService(Document); + spyOn(document, 'getElementById'); + MockRender( + RenderRealComponent, + {}, + { + providers: [ + { + provide: DOCUMENT, + useValue: document, + }, + ], + } + ); + expect(document.getElementById).toHaveBeenCalledWith('test'); + }); }); diff --git a/lib/mock-render/mock-render.ts b/lib/mock-render/mock-render.ts index 022edad58d..c9f3b64e78 100644 --- a/lib/mock-render/mock-render.ts +++ b/lib/mock-render/mock-render.ts @@ -1,6 +1,6 @@ // tslint:disable:unified-signatures -import { Component, DebugElement, Type } from '@angular/core'; +import { Component, DebugElement, Provider, Type } from '@angular/core'; import { ComponentFixture, getTestBed, TestBed } from '@angular/core/testing'; import { directiveResolver } from '../common/reflect'; @@ -30,10 +30,15 @@ export type DebugElementField = export type DebugElementType = { componentInstance: T } & Pick; +export interface IMockRenderOptions { + detectChanges?: boolean; + providers?: Provider[]; +} + function MockRender( template: Type, params: TComponent, - detectChanges?: boolean + detectChanges?: boolean | IMockRenderOptions ): ComponentFixture & { point: DebugElementType }; // without params we shouldn't autocomplete any keys of any types. @@ -44,7 +49,7 @@ function MockRender( function MockRender( template: string, params: TComponent, - detectChanges?: boolean + detectChanges?: boolean | IMockRenderOptions ): ComponentFixture; // without params we shouldn't autocomplete any keys of any types. @@ -53,8 +58,10 @@ function MockRender(template: string): ComponentFixture; function MockRender( template: string | Type, params?: TComponent, - detectChanges = true + flags: boolean | IMockRenderOptions = true ): ComponentFixture { + const flagsObject: IMockRenderOptions = typeof flags === 'boolean' ? { detectChanges: flags } : flags; + let mockedTemplate = ''; if (typeof template === 'string') { mockedTemplate = template; @@ -84,6 +91,7 @@ function MockRender( mockedTemplate += `>`; } const options: Component = { + providers: flagsObject.providers, selector: 'mock-render', template: mockedTemplate, }; @@ -107,7 +115,7 @@ function MockRender( const fixture: any = TestBed.createComponent(component); - if (detectChanges) { + if (flagsObject.detectChanges) { fixture.detectChanges(); }