From d9f292cac49374841b1d0716f6c1ce598a935dcc Mon Sep 17 00:00:00 2001 From: Tim Deschryver Date: Fri, 15 Jun 2018 14:53:50 +0200 Subject: [PATCH] feat: allow creation of component via its type --- projects/ngx-testing-library/package.json | 3 +- .../ngx-testing-library/src/lib/models.ts | 51 +++++++++++ .../src/lib/ngx-testing-library.ts | 86 ++++++++----------- .../ngx-testing-library/src/public_api.ts | 1 + .../ngx-testing-library/tests/counter.spec.ts | 71 ++++++++++++++- 5 files changed, 159 insertions(+), 53 deletions(-) create mode 100644 projects/ngx-testing-library/src/lib/models.ts diff --git a/projects/ngx-testing-library/package.json b/projects/ngx-testing-library/package.json index d6358e8d..e050387f 100644 --- a/projects/ngx-testing-library/package.json +++ b/projects/ngx-testing-library/package.json @@ -23,8 +23,7 @@ "homepage": "https://github.com/tdeschryver/ngx-testing-library#readme", "peerDependencies": { "@angular/common": "^6.0.0-rc.0 || ^6.0.0", - "@angular/core": "^6.0.0-rc.0 || ^6.0.0", - "@angular/testing": "^6.0.0-rc.0 || ^6.0.0" + "@angular/core": "^6.0.0-rc.0 || ^6.0.0" }, "dependencies": { "dom-testing-library": "^2.5.0" diff --git a/projects/ngx-testing-library/src/lib/models.ts b/projects/ngx-testing-library/src/lib/models.ts new file mode 100644 index 00000000..b5865b53 --- /dev/null +++ b/projects/ngx-testing-library/src/lib/models.ts @@ -0,0 +1,51 @@ +import { Type } from '@angular/core'; + +export interface Result { + container: any; + get: (token: any, notFoundValue?: any) => any; + getComponentInstance: (selectorOrComponent: string | Type) => T; + debug: () => void; + detectChanges: (checkNoChanges?: boolean) => void; + fixture: any; + queryByPlaceholderText: any; + queryAllByPlaceholderText: any; + getByPlaceholderText: any; + getAllByPlaceholderText: any; + queryByText: any; + queryAllByText: any; + getByText: any; + getAllByText: any; + queryByLabelText: any; + queryAllByLabelText: any; + getByLabelText: any; + getAllByLabelText: any; + queryByAltText: any; + queryAllByAltText: any; + getByAltText: any; + getAllByAltText: any; + queryByTestId: any; + queryAllByTestId: any; + getByTestId: any; + getAllByTestId: any; + queryByTitle: any; + queryAllByTitle: any; + getByTitle: any; + getAllByTitle: any; + queryByValue: any; + queryAllByValue: any; + getByValue: any; + getAllByValue: any; +} + +export interface Options { + detectChanges?: boolean; + declarations: any[]; + providers?: any[]; + imports?: any[]; + schemas?: any[]; +} + +export interface ComponentInput { + component: Type; + parameters?: Partial; +} diff --git a/projects/ngx-testing-library/src/lib/ngx-testing-library.ts b/projects/ngx-testing-library/src/lib/ngx-testing-library.ts index 5135bf92..63c5f0e5 100644 --- a/projects/ngx-testing-library/src/lib/ngx-testing-library.ts +++ b/projects/ngx-testing-library/src/lib/ngx-testing-library.ts @@ -1,68 +1,51 @@ -import { Component, NgModule } from '@angular/core'; +import { Component, NgModule, Type } from '@angular/core'; import { TestBed, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { getQueriesForElement, prettyDOM } from 'dom-testing-library'; +import { Options, Result, ComponentInput } from './models'; + @Component({ selector: 'test-component', template: '' }) class TestComponent {} -export async function createComponent( - template: string, - { detectChanges = true, declarations = [], providers = [], imports = [], schemas = [] } = {}, -): Promise<{ - container: any; - get: (token: any, notFoundValue?: any) => any; - getComponentInstance: (selector: string) => T; - debug: () => void; - detectChanges: (checkNoChanges?: boolean) => void; - fixture: any; - queryByPlaceholderText: any; - queryAllByPlaceholderText: any; - getByPlaceholderText: any; - getAllByPlaceholderText: any; - queryByText: any; - queryAllByText: any; - getByText: any; - getAllByText: any; - queryByLabelText: any; - queryAllByLabelText: any; - getByLabelText: any; - getAllByLabelText: any; - queryByAltText: any; - queryAllByAltText: any; - getByAltText: any; - getAllByAltText: any; - queryByTestId: any; - queryAllByTestId: any; - getByTestId: any; - getAllByTestId: any; - queryByTitle: any; - queryAllByTitle: any; - getByTitle: any; - getAllByTitle: any; - queryByValue: any; - queryAllByValue: any; - getByValue: any; - getAllByValue: any; -}> { +export async function createComponent(template: string, options: Options): Promise; +export async function createComponent(component: ComponentInput, options: Options): Promise; +export async function createComponent( + templateOrComponent: string | ComponentInput, + { detectChanges = true, declarations = [], providers = [], imports = [], schemas = [] }: Options, +): Promise { + const isTemplate = typeof templateOrComponent === 'string'; + const extraDeclarations = isTemplate ? [TestComponent] : []; + TestBed.configureTestingModule({ - declarations: [TestComponent, ...declarations], + declarations: [...declarations, ...extraDeclarations], providers: [...providers], imports: [...imports], schemas: [...schemas], }); - TestBed.overrideComponent(TestComponent, { - set: { - template, - }, - }); + if (isTemplate) { + TestBed.overrideComponent(TestComponent, { + set: { + template: templateOrComponent, + }, + }); + } await TestBed.compileComponents(); - const fixture = TestBed.createComponent(TestComponent); - if (detectChanges) { - fixture.detectChanges(); + let fixture; + if (isTemplate) { + fixture = TestBed.createComponent(TestComponent); + if (detectChanges) { + fixture.detectChanges(); + } + } else { + const { component, parameters = [] } = >templateOrComponent; + fixture = TestBed.createComponent(component); + for (const key of Object.keys(parameters)) { + fixture.componentInstance[key] = parameters[key]; + } } // Currently this isn't perfect because the typings from dom-testing-library are for TS 2.8 @@ -70,7 +53,10 @@ export async function createComponent( fixture, container: fixture.nativeElement, get: TestBed.get, - getComponentInstance: (selector: string) => fixture.debugElement.query(By.css(selector)).componentInstance as T, + getComponentInstance: (selectorOrComponent: string | C) => + typeof selectorOrComponent === 'string' + ? fixture.debugElement.query(By.css(selectorOrComponent)).componentInstance + : fixture.componentInstance, debug: () => console.log(prettyDOM(fixture.nativeElement)), detectChanges: (checkNoChanges?: boolean) => fixture.detectChanges(checkNoChanges), ...getQueriesForElement(fixture.nativeElement), diff --git a/projects/ngx-testing-library/src/public_api.ts b/projects/ngx-testing-library/src/public_api.ts index 13d3dbd0..919dbcff 100644 --- a/projects/ngx-testing-library/src/public_api.ts +++ b/projects/ngx-testing-library/src/public_api.ts @@ -2,5 +2,6 @@ * Public API Surface of ngx-testing-library */ +export * from './lib/models'; export * from './lib/ngx-testing-library'; export { fireEvent } from 'dom-testing-library'; diff --git a/projects/ngx-testing-library/tests/counter.spec.ts b/projects/ngx-testing-library/tests/counter.spec.ts index 15cca7af..a5cbacd5 100644 --- a/projects/ngx-testing-library/tests/counter.spec.ts +++ b/projects/ngx-testing-library/tests/counter.spec.ts @@ -20,7 +20,7 @@ export class CounterComponent { } test('Counter actions', async () => { - const { detectChanges, getByText, getByTestId, debug } = await createComponent('', { + const { detectChanges, getByText, getByTestId } = await createComponent('', { declarations: [CounterComponent], }); @@ -54,3 +54,72 @@ test('Counter actions - fireEvent', async () => { expect(getByText('Current Count: 12')).toBeTruthy(); expect(getByTestId('count').textContent).toBe('Current Count: 12'); }); + +test('Counter actions via component', async () => { + const { getComponentInstance } = await createComponent( + { + component: CounterComponent, + parameters: { + counter: 10, + }, + }, + { + declarations: [CounterComponent], + }, + ); + + const counter = getComponentInstance(CounterComponent); + counter.increment(); + counter.increment(); + counter.increment(); + expect(counter.counter).toBe(13); + + counter.decrement(); + expect(counter.counter).toBe(12); +}); + +test('Counter actions via component without parameters', async () => { + const { getComponentInstance } = await createComponent( + { + component: CounterComponent, + }, + { + declarations: [CounterComponent], + }, + ); + + const counter = getComponentInstance(CounterComponent); + counter.increment(); + counter.increment(); + counter.increment(); + expect(counter.counter).toBe(3); + + counter.decrement(); + expect(counter.counter).toBe(2); +}); + +test('Counter via component - test template', async () => { + const { getByText, detectChanges, getByTestId } = await createComponent( + { + component: CounterComponent, + parameters: { + counter: 10, + }, + }, + { + declarations: [CounterComponent], + }, + ); + + getByText('+').click(); + getByText('+').click(); + getByText('+').click(); + detectChanges(); + expect(getByText('Current Count: 13')).toBeTruthy(); + expect(getByTestId('count').textContent).toBe('Current Count: 13'); + + getByText('-').click(); + detectChanges(); + expect(getByText('Current Count: 12')).toBeTruthy(); + expect(getByTestId('count').textContent).toBe('Current Count: 12'); +});