diff --git a/.circleci/config.yml b/.circleci/config.yml index 792aa529..b4ba5692 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,11 +2,11 @@ version: 2 job_defaults: &job_defaults docker: - - image: circleci/node:latest + - image: circleci/node:12.9.1 working_directory: ~/project/repo -cache_key: &cache_key testing-library-deps-cache-{{ .Branch }}-{{ checksum "yarn.lock" }} -dist_key: &dist_key testing-library-dist-{{ .Revision }} +cache_key: &cache_key angular-testing-library-deps-cache-{{ checksum "yarn.lock" }} +dist_key: &dist_key angular-testing-library-dist-{{ .Revision }} jobs: install: @@ -17,7 +17,7 @@ jobs: key: *cache_key - run: name: install-dependencies - command: yarn + command: yarn --frozen-lockfile - save_cache: key: *cache_key paths: @@ -55,7 +55,7 @@ jobs: - save_cache: key: *dist_key paths: - - dist + - dist test-app: <<: *job_defaults @@ -78,8 +78,8 @@ jobs: - restore_cache: key: *dist_key - run: - name: release - command: yarn semantic-release || true + name: release + command: yarn semantic-release || true workflows: version: 2 diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts index 789ec305..e6d69583 100644 --- a/projects/testing-library/src/lib/models.ts +++ b/projects/testing-library/src/lib/models.ts @@ -32,6 +32,11 @@ export interface RenderResult * For more info see https://angular.io/api/core/testing/ComponentFixture#detectChanges */ detectChanges: () => void; + /** + * @description + * Re-render the same component with different props. + */ + rerender: (componentProperties: Partial) => void; /** * @description * The Angular `ComponentFixture` of the component or the wrapper. diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index 1a213318..4917d62b 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -91,10 +91,14 @@ export async function render( {} as FireFunction & FireObject, ); + const rerender = (rerenderedProperties: Partial) => { + setComponentProperties(fixture, { componentProperties: rerenderedProperties }); + detectChanges(); + }; + let router = routes ? (TestBed.get(Router) as Router) : null; const zone = TestBed.get(NgZone) as NgZone; - - async function navigate(elementOrPath: Element | string, basePath = '') { + const navigate = async (elementOrPath: Element | string, basePath = '') => { if (!router) { router = TestBed.get(Router) as Router; } @@ -105,20 +109,20 @@ export async function render( await zone.run(() => (result = router.navigate([basePath + href]))); detectChanges(); return result; - } - const debugElement = fixture.debugElement.query(By.directive(sut)); + }; return { fixture, - debugElement, + detectChanges, + navigate, + rerender, + debugElement: fixture.debugElement.query(By.directive(sut)), container: fixture.nativeElement, debug: (element = fixture.nativeElement) => console.log(prettyDOM(element)), - detectChanges, - ...getQueriesForElement(fixture.nativeElement, queries), - ...eventsWithDetectChanges, type: createType(eventsWithDetectChanges), selectOptions: createSelectOptions(eventsWithDetectChanges), - navigate, + ...getQueriesForElement(fixture.nativeElement, queries), + ...eventsWithDetectChanges, }; } diff --git a/projects/testing-library/tests/render.spec.ts b/projects/testing-library/tests/render.spec.ts index cd83237e..6efd020a 100644 --- a/projects/testing-library/tests/render.spec.ts +++ b/projects/testing-library/tests/render.spec.ts @@ -25,7 +25,7 @@ test('creates queries and events', async () => { }) export class FixtureModule {} describe('excludeComponentDeclaration', () => { - test('should not throw if component is declared in an import', async () => { + test('will throw if component is declared in an import', async () => { await render(FixtureComponent, { imports: [FixtureModule], excludeComponentDeclaration: true, @@ -34,13 +34,13 @@ describe('excludeComponentDeclaration', () => { }); describe('animationModule', () => { - test('should add NoopAnimationsModule by default', async () => { + test('adds NoopAnimationsModule by default', async () => { await render(FixtureComponent); const noopAnimationsModule = TestBed.get(NoopAnimationsModule); expect(noopAnimationsModule).toBeDefined(); }); - test('should not add NoopAnimationsModule if BrowserAnimationsModule is an import', async () => { + test('does not add NoopAnimationsModule if BrowserAnimationsModule is an import', async () => { await render(FixtureComponent, { imports: [BrowserAnimationsModule], }); diff --git a/projects/testing-library/tests/rerender.spec.ts b/projects/testing-library/tests/rerender.spec.ts new file mode 100644 index 00000000..b653d1da --- /dev/null +++ b/projects/testing-library/tests/rerender.spec.ts @@ -0,0 +1,24 @@ +import { Component, Input } from '@angular/core'; +import { render } from '../src/public_api'; + +@Component({ + selector: 'fixture', + template: ` + {{ name }} + `, +}) +class FixtureComponent { + @Input() name = 'Sarah'; +} + +test('will rerender the component with updated props', async () => { + const component = await render(FixtureComponent); + component.getByText('Sarah'); + + const name = 'Mark'; + component.rerender({ + name, + }); + + component.getByText(name); +});