diff --git a/apps/example-app/src/app/examples/21-deferable-view.component.ts b/apps/example-app/src/app/examples/21-deferable-view.component.ts deleted file mode 100644 index ce47a58..0000000 --- a/apps/example-app/src/app/examples/21-deferable-view.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-deferable-view-child', - template: `

Hello from deferred child component

`, - standalone: true, -}) -export class DeferableViewChildComponent {} - -@Component({ - template: ` - @defer (on timer(2s)) { - - } @placeholder { -

Hello from placeholder

- } @loading { -

Hello from loading

- } @error { -

Hello from error

- } - `, - imports: [DeferableViewChildComponent], - standalone: true, -}) -export class DeferableViewComponent {} diff --git a/apps/example-app/src/app/examples/21-deferable-view.spec.ts b/apps/example-app/src/app/examples/21-deferable-view.spec.ts deleted file mode 100644 index 8495387..0000000 --- a/apps/example-app/src/app/examples/21-deferable-view.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { render, screen } from '@testing-library/angular'; -import { DeferBlockState } from '@angular/core/testing'; -import { DeferableViewComponent } from './21-deferable-view.component'; - -test('renders deferred views based on state', async () => { - const { renderDeferBlock } = await render(DeferableViewComponent); - - expect(screen.getByText(/Hello from placeholder/i)).toBeInTheDocument(); - - await renderDeferBlock(DeferBlockState.Loading); - expect(screen.getByText(/Hello from loading/i)).toBeInTheDocument(); - - await renderDeferBlock(DeferBlockState.Complete); - expect(screen.getByText(/Hello from deferred child component/i)).toBeInTheDocument(); -}); - -test('initially renders deferred views based on given state', async () => { - await render(DeferableViewComponent, { - deferBlockStates: DeferBlockState.Error, - }); - - expect(screen.getByText(/Hello from error/i)).toBeInTheDocument(); -}); diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts index f148ee2..2e198a6 100644 --- a/projects/testing-library/src/lib/models.ts +++ b/projects/testing-library/src/lib/models.ts @@ -1,5 +1,5 @@ import { Type, DebugElement } from '@angular/core'; -import { ComponentFixture, DeferBlockState, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Routes } from '@angular/router'; import { BoundFunction, Queries, queries, Config as dtlConfig, PrettyDOMOptions } from '@testing-library/dom'; @@ -63,11 +63,6 @@ export interface RenderResult extend 'componentProperties' | 'componentInputs' | 'componentOutputs' | 'detectChangesOnRender' >, ) => Promise; - /** - * @description - * Set the state of a deferrable block. - */ - renderDeferBlock: (deferBlockState: DeferBlockState, deferBlockIndex?: number) => Promise; } export interface RenderComponentOptions { @@ -368,8 +363,6 @@ export interface RenderComponentOptions void; - - deferBlockStates?: DeferBlockState | { deferBlockState: DeferBlockState; deferBlockIndex: number }[]; } export interface ComponentOverride { diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index 48128cc..65932fc 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -9,7 +9,7 @@ import { ApplicationInitStatus, isStandalone, } from '@angular/core'; -import { ComponentFixture, DeferBlockState, TestBed, tick } from '@angular/core/testing'; +import { ComponentFixture, TestBed, tick } from '@angular/core/testing'; import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NavigationExtras, Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; @@ -65,7 +65,6 @@ export async function render( removeAngularAttributes = false, defaultImports = [], initialRoute = '', - deferBlockStates = undefined, configureTestBed = () => { /* noop*/ }, @@ -161,19 +160,10 @@ export async function render( } } + let fixture: ComponentFixture; let detectChanges: () => void; - const fixture = await renderFixture(componentProperties, componentInputs, componentOutputs); - - if (deferBlockStates) { - if (Array.isArray(deferBlockStates)) { - for (const deferBlockState of deferBlockStates) { - await renderDeferBlock(fixture, deferBlockState.deferBlockState, deferBlockState.deferBlockIndex); - } - } else { - await renderDeferBlock(fixture, deferBlockStates); - } - } + await renderFixture(componentProperties, componentInputs, componentOutputs); let renderedPropKeys = Object.keys(componentProperties); let renderedInputKeys = Object.keys(componentInputs); @@ -220,61 +210,60 @@ export async function render( }; return { + // @ts-ignore: fixture assigned fixture, detectChanges: () => detectChanges(), navigate, rerender, - renderDeferBlock: async (deferBlockState: DeferBlockState, deferBlockIndex?: number) => { - await renderDeferBlock(fixture, deferBlockState, deferBlockIndex); - }, + // @ts-ignore: fixture assigned debugElement: fixture.debugElement, + // @ts-ignore: fixture assigned container: fixture.nativeElement, debug: (element = fixture.nativeElement, maxLength, options) => Array.isArray(element) ? element.forEach((e) => console.log(dtlPrettyDOM(e, maxLength, options))) : console.log(dtlPrettyDOM(element, maxLength, options)), + // @ts-ignore: fixture assigned ...replaceFindWithFindAndDetectChanges(dtlGetQueriesForElement(fixture.nativeElement, queries)), }; - async function renderFixture( - properties: Partial, - inputs: Partial, - outputs: Partial, - ): Promise> { - const createdFixture = await createComponent(componentContainer); - setComponentProperties(createdFixture, properties); - setComponentInputs(createdFixture, inputs); - setComponentOutputs(createdFixture, outputs); + async function renderFixture(properties: Partial, inputs: Partial, outputs: Partial) { + if (fixture) { + cleanupAtFixture(fixture); + } + + fixture = await createComponent(componentContainer); + setComponentProperties(fixture, properties); + setComponentInputs(fixture, inputs); + setComponentOutputs(fixture, outputs); if (removeAngularAttributes) { - createdFixture.nativeElement.removeAttribute('ng-version'); - const idAttribute = createdFixture.nativeElement.getAttribute('id'); + fixture.nativeElement.removeAttribute('ng-version'); + const idAttribute = fixture.nativeElement.getAttribute('id'); if (idAttribute && idAttribute.startsWith('root')) { - createdFixture.nativeElement.removeAttribute('id'); + fixture.nativeElement.removeAttribute('id'); } } - mountedFixtures.add(createdFixture); + mountedFixtures.add(fixture); let isAlive = true; - createdFixture.componentRef.onDestroy(() => (isAlive = false)); + fixture.componentRef.onDestroy(() => (isAlive = false)); - if (hasOnChangesHook(createdFixture.componentInstance) && Object.keys(properties).length > 0) { + if (hasOnChangesHook(fixture.componentInstance) && Object.keys(properties).length > 0) { const changes = getChangesObj(null, componentProperties); - createdFixture.componentInstance.ngOnChanges(changes); + fixture.componentInstance.ngOnChanges(changes); } detectChanges = () => { if (isAlive) { - createdFixture.detectChanges(); + fixture.detectChanges(); } }; if (detectChangesOnRender) { detectChanges(); } - - return createdFixture; } } @@ -440,30 +429,6 @@ function addAutoImports( return [...imports, ...components(), ...animations(), ...routing()]; } -async function renderDeferBlock( - fixture: ComponentFixture, - deferBlockState: DeferBlockState, - deferBlockIndex?: number, -) { - const deferBlockFixtures = await fixture.getDeferBlocks(); - - if (deferBlockIndex !== undefined) { - if (deferBlockIndex < 0) { - throw new Error('deferBlockIndex must be a positive number'); - } - - const deferBlockFixture = deferBlockFixtures[deferBlockIndex]; - if (!deferBlockFixture) { - throw new Error(`Could not find a deferrable block with index '${deferBlockIndex}'`); - } - await deferBlockFixture.render(deferBlockState); - } else { - for (const deferBlockFixture of deferBlockFixtures) { - await deferBlockFixture.render(deferBlockState); - } - } -} - /** * Wrap waitFor to invoke the Angular change detection cycle before invoking the callback */ diff --git a/projects/testing-library/tests/defer-blocks.spec.ts b/projects/testing-library/tests/defer-blocks.spec.ts deleted file mode 100644 index 9c2985b..0000000 --- a/projects/testing-library/tests/defer-blocks.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Component } from '@angular/core'; -import { DeferBlockState } from '@angular/core/testing'; -import { render, screen } from '../src/public_api'; - -test('renders a defer block in different states using the official API', async () => { - const { fixture } = await render(FixtureComponent); - - const deferBlockFixture = (await fixture.getDeferBlocks())[0]; - - await deferBlockFixture.render(DeferBlockState.Loading); - expect(screen.getByText(/loading/i)).toBeInTheDocument(); - expect(screen.queryByText(/Defer block content/i)).not.toBeInTheDocument(); - - await deferBlockFixture.render(DeferBlockState.Complete); - expect(screen.getByText(/Defer block content/i)).toBeInTheDocument(); - expect(screen.queryByText(/load/i)).not.toBeInTheDocument(); -}); - -test('renders a defer block in different states using ATL', async () => { - const { renderDeferBlock } = await render(FixtureComponent); - - await renderDeferBlock(DeferBlockState.Loading); - expect(screen.getByText(/loading/i)).toBeInTheDocument(); - expect(screen.queryByText(/Defer block content/i)).not.toBeInTheDocument(); - - await renderDeferBlock(DeferBlockState.Complete, 0); - expect(screen.getByText(/Defer block content/i)).toBeInTheDocument(); - expect(screen.queryByText(/load/i)).not.toBeInTheDocument(); -}); - -test('renders a defer block initially in the loading state', async () => { - await render(FixtureComponent, { - deferBlockStates: DeferBlockState.Loading, - }); - - expect(screen.getByText(/loading/i)).toBeInTheDocument(); - expect(screen.queryByText(/Defer block content/i)).not.toBeInTheDocument(); -}); - -test('renders a defer block initially in the complete state', async () => { - await render(FixtureComponent, { - deferBlockStates: DeferBlockState.Complete, - }); - - expect(screen.getByText(/Defer block content/i)).toBeInTheDocument(); - expect(screen.queryByText(/load/i)).not.toBeInTheDocument(); -}); - -test('renders a defer block in an initial state using the array syntax', async () => { - await render(FixtureComponent, { - deferBlockStates: [{ deferBlockState: DeferBlockState.Complete, deferBlockIndex: 0 }], - }); - - expect(screen.getByText(/Defer block content/i)).toBeInTheDocument(); - expect(screen.queryByText(/load/i)).not.toBeInTheDocument(); -}); - -@Component({ - template: ` - @defer { -

Defer block content

- } @loading { -

Loading...

- } - `, -}) -class FixtureComponent {}