From 73b0339fdc42966c99df6c2be1a9b5b5d4aba066 Mon Sep 17 00:00:00 2001 From: Gregor Woiwode Date: Mon, 2 Sep 2019 21:12:21 +0200 Subject: [PATCH 1/3] feat(render): expose detectChanges --- projects/testing-library/src/lib/models.ts | 3 +- .../src/lib/testing-library.ts | 13 +++--- .../tests/detect-changes.spec.ts | 41 +++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 projects/testing-library/tests/detect-changes.spec.ts diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts index 7211a12e..244bac29 100644 --- a/projects/testing-library/src/lib/models.ts +++ b/projects/testing-library/src/lib/models.ts @@ -1,6 +1,6 @@ import { Type } from '@angular/core'; import { ComponentFixture } from '@angular/core/testing'; -import { FireObject, Queries, queries, BoundFunction } from '@testing-library/dom'; +import { BoundFunction, FireObject, Queries, queries } from '@testing-library/dom'; import { UserEvents } from './user-events'; export type RenderResultQueries = { [P in keyof Q]: BoundFunction }; @@ -21,6 +21,7 @@ export interface RenderResult extends RenderResultQueries, FireObject, UserEvent * element: The to be printed HTML element, if not provided it will log the whole component's DOM */ debug: (element?: HTMLElement) => void; + detectChanges: () => void; /** * @description * The Angular `ComponentFixture` of the component. diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index 41c5c50f..1b8b43ff 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -1,10 +1,10 @@ -import { Component, OnInit, ElementRef, Type, DebugElement } from '@angular/core'; +import { Component, DebugElement, ElementRef, OnInit, Type } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NoopAnimationsModule, BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { getQueriesForElement, prettyDOM, fireEvent, FireObject, FireFunction } from '@testing-library/dom'; -import { RenderResult, RenderOptions } from './models'; -import { createType, createSelectOptions } from './user-events'; +import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { fireEvent, FireFunction, FireObject, getQueriesForElement, prettyDOM } from '@testing-library/dom'; +import { RenderOptions, RenderResult } from './models'; +import { createSelectOptions, createType } from './user-events'; @Component({ selector: 'wrapper-component', template: '' }) class WrapperComponent implements OnInit { @@ -84,6 +84,7 @@ export async function render( fixture, container: fixture.nativeElement, debug: (element = fixture.nativeElement) => console.log(prettyDOM(element)), + detectChanges: () => fixture.detectChanges(), ...getQueriesForElement(fixture.nativeElement, queries), ...eventsWithDetectChanges, type: createType(eventsWithDetectChanges), diff --git a/projects/testing-library/tests/detect-changes.spec.ts b/projects/testing-library/tests/detect-changes.spec.ts new file mode 100644 index 00000000..a72e77de --- /dev/null +++ b/projects/testing-library/tests/detect-changes.spec.ts @@ -0,0 +1,41 @@ +import { Component, OnInit } from '@angular/core'; +import { fakeAsync, tick } from '@angular/core/testing'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { delay } from 'rxjs/operators'; +import { render } from '../src/public_api'; + +@Component({ + selector: 'fixture', + template: ` + + + `, +}) +class FixtureComponent implements OnInit { + inputControl = new FormControl(); + caption = 'Button'; + + ngOnInit() { + this.inputControl.valueChanges.pipe(delay(400)).subscribe(() => (this.caption = 'Button updated after 400ms')); + } +} + +test('allows detecting changes directly', async () => { + const { getByTestId, type } = await render(FixtureComponent, { imports: [ReactiveFormsModule] }); + + type(getByTestId('input'), 'What a great day!'); + expect(getByTestId('button').innerHTML).toBe('Button'); +}); + +test('allows detecting changes directly', fakeAsync(async () => { + const { getByTestId, type, detectChanges } = await render(FixtureComponent, { + imports: [ReactiveFormsModule], + }); + + type(getByTestId('input'), 'What a great day!'); + + tick(500); + detectChanges(); + + expect(getByTestId('button').innerHTML).toBe('Button updated after 400ms'); +})); From 9661f3ac4c7b15eaeb462b514dd3e61643fe876b Mon Sep 17 00:00:00 2001 From: Gregor Woiwode Date: Mon, 2 Sep 2019 21:30:20 +0200 Subject: [PATCH 2/3] docs(RenderResult): add jsdoc comment --- projects/testing-library/src/lib/models.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts index 244bac29..d87720d0 100644 --- a/projects/testing-library/src/lib/models.ts +++ b/projects/testing-library/src/lib/models.ts @@ -21,6 +21,12 @@ export interface RenderResult extends RenderResultQueries, FireObject, UserEvent * element: The to be printed HTML element, if not provided it will log the whole component's DOM */ debug: (element?: HTMLElement) => void; + /** + * @description + * Trigger a change detection cycle for the component. + * + * For more info see https://angular.io/api/core/testing/ComponentFixture#detectChanges + */ detectChanges: () => void; /** * @description From b4a48e532afe43e7d49e836a69379e03b1edc553 Mon Sep 17 00:00:00 2001 From: Gregor Woiwode Date: Mon, 2 Sep 2019 21:37:17 +0200 Subject: [PATCH 3/3] test(detectChanges): refine test description --- .../tests/detect-changes.spec.ts | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/projects/testing-library/tests/detect-changes.spec.ts b/projects/testing-library/tests/detect-changes.spec.ts index a72e77de..40f68812 100644 --- a/projects/testing-library/tests/detect-changes.spec.ts +++ b/projects/testing-library/tests/detect-changes.spec.ts @@ -20,22 +20,24 @@ class FixtureComponent implements OnInit { } } -test('allows detecting changes directly', async () => { - const { getByTestId, type } = await render(FixtureComponent, { imports: [ReactiveFormsModule] }); +describe('detectChanges', () => { + test('does not recognize change if execution is delayed', async () => { + const { getByTestId, type } = await render(FixtureComponent, { imports: [ReactiveFormsModule] }); - type(getByTestId('input'), 'What a great day!'); - expect(getByTestId('button').innerHTML).toBe('Button'); -}); - -test('allows detecting changes directly', fakeAsync(async () => { - const { getByTestId, type, detectChanges } = await render(FixtureComponent, { - imports: [ReactiveFormsModule], + type(getByTestId('input'), 'What a great day!'); + expect(getByTestId('button').innerHTML).toBe('Button'); }); - type(getByTestId('input'), 'What a great day!'); + test('exposes detectChanges triggering a change detection cycle', fakeAsync(async () => { + const { getByTestId, type, detectChanges } = await render(FixtureComponent, { + imports: [ReactiveFormsModule], + }); - tick(500); - detectChanges(); + type(getByTestId('input'), 'What a great day!'); - expect(getByTestId('button').innerHTML).toBe('Button updated after 400ms'); -})); + tick(500); + detectChanges(); + + expect(getByTestId('button').innerHTML).toBe('Button updated after 400ms'); + })); +});