diff --git a/apps/example-app-jest/src/app/examples/02-input-output.spec.ts b/apps/example-app-jest/src/app/examples/02-input-output.spec.ts index 7645836..96b58ba 100644 --- a/apps/example-app-jest/src/app/examples/02-input-output.spec.ts +++ b/apps/example-app-jest/src/app/examples/02-input-output.spec.ts @@ -66,6 +66,34 @@ test('is possible to set input and listen for output (deprecated)', async () => expect(sendValue).toHaveBeenCalledWith(50); }); +test('is possible to set input and listen for output with the template syntax', async () => { + const user = userEvent.setup(); + const sendSpy = jest.fn(); + + await render('', { + imports: [InputOutputComponent], + componentProperties: { + sendValue: sendSpy, + }, + providers: [provideZoneChangeDetection()], + }); + + const incrementControl = screen.getByRole('button', { name: /increment/i }); + const sendControl = screen.getByRole('button', { name: /send/i }); + const valueControl = screen.getByTestId('value'); + + expect(valueControl).toHaveTextContent('47'); + + await user.click(incrementControl); + await user.click(incrementControl); + await user.click(incrementControl); + expect(valueControl).toHaveTextContent('50'); + + await user.click(sendControl); + expect(sendSpy).toHaveBeenCalledTimes(1); + expect(sendSpy).toHaveBeenCalledWith(50); +}); + test('is possible to set input and listen for output with the template syntax (deprecated)', async () => { const user = userEvent.setup(); const sendSpy = jest.fn(); diff --git a/apps/example-app-jest/src/app/examples/20-test-harness.spec.ts b/apps/example-app-jest/src/app/examples/20-test-harness.spec.ts new file mode 100644 index 0000000..a2ddd74 --- /dev/null +++ b/apps/example-app-jest/src/app/examples/20-test-harness.spec.ts @@ -0,0 +1,39 @@ +import { provideZoneChangeDetection } from '@angular/core'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { MatSnackBarHarness } from '@angular/material/snack-bar/testing'; +import { render, screen } from '@testing-library/angular'; +import userEvent from '@testing-library/user-event'; + +import { HarnessComponent } from './20-test-harness'; + +test.skip('can be used with TestHarness', async () => { + const view = await render(``, { + imports: [HarnessComponent], + providers: [provideZoneChangeDetection()], + }); + const loader = TestbedHarnessEnvironment.documentRootLoader(view.fixture); + + const buttonHarness = await loader.getHarness(MatButtonHarness); + const button = await buttonHarness.host(); + button.click(); + + const snackbarHarness = await loader.getHarness(MatSnackBarHarness); + expect(await snackbarHarness.getMessage()).toMatch(/Pizza Party!!!/i); +}); + +test.skip('can be used in combination with TestHarness', async () => { + const user = userEvent.setup(); + + const view = await render(HarnessComponent, { + providers: [provideZoneChangeDetection()], + }); + const loader = TestbedHarnessEnvironment.documentRootLoader(view.fixture); + + await user.click(screen.getByRole('button')); + + const snackbarHarness = await loader.getHarness(MatSnackBarHarness); + expect(await snackbarHarness.getMessage()).toMatch(/Pizza Party!!!/i); + + expect(screen.getByText(/Pizza Party!!!/i)).toBeInTheDocument(); +}); diff --git a/apps/example-app-jest/src/app/examples/20-test-harness.ts b/apps/example-app-jest/src/app/examples/20-test-harness.ts new file mode 100644 index 0000000..0ecb7b3 --- /dev/null +++ b/apps/example-app-jest/src/app/examples/20-test-harness.ts @@ -0,0 +1,19 @@ +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; + +@Component({ + selector: 'atl-harness', + standalone: true, + imports: [MatButtonModule, MatSnackBarModule], + template: ` + + `, +}) +export class HarnessComponent { + private snackBar = inject(MatSnackBar); + + openSnackBar() { + return this.snackBar.open('Pizza Party!!!'); + } +} diff --git a/apps/example-app/src/app/examples/02-input-output.spec.ts b/apps/example-app/src/app/examples/02-input-output.spec.ts index 8dcd289..b554f1f 100644 --- a/apps/example-app/src/app/examples/02-input-output.spec.ts +++ b/apps/example-app/src/app/examples/02-input-output.spec.ts @@ -33,13 +33,13 @@ test('is possible to set input and listen for output', async () => { expect(sendValue).toHaveBeenCalledWith(50); }); -test.skip('is possible to set input and listen for output with the template syntax', async () => { +test('is possible to set input and listen for output with the template syntax', async () => { const user = userEvent.setup(); const sendSpy = vi.fn(); await render('', { imports: [InputOutputComponent], - on: { + componentProperties: { sendValue: sendSpy, }, }); diff --git a/apps/example-app/src/app/examples/20-test-harness.spec.ts b/apps/example-app/src/app/examples/20-test-harness.spec.ts index bfd0302..ff45cdb 100644 --- a/apps/example-app/src/app/examples/20-test-harness.spec.ts +++ b/apps/example-app/src/app/examples/20-test-harness.spec.ts @@ -7,7 +7,7 @@ import userEvent from '@testing-library/user-event'; import { HarnessComponent } from './20-test-harness'; -test.skip('can be used with TestHarness', async () => { +test('can be used with TestHarness', async () => { const view = await render(``, { imports: [HarnessComponent], }); @@ -21,7 +21,7 @@ test.skip('can be used with TestHarness', async () => { expect(await snackbarHarness.getMessage()).toMatch(/Pizza Party!!!/i); }); -test.skip('can be used in combination with TestHarness', async () => { +test('can be used in combination with TestHarness', async () => { const user = userEvent.setup(); const view = await render(HarnessComponent); diff --git a/projects/testing-library/src/tests/integration.spec.ts b/projects/testing-library/src/tests/integration.spec.ts index 9257ca0..b39dec2 100644 --- a/projects/testing-library/src/tests/integration.spec.ts +++ b/projects/testing-library/src/tests/integration.spec.ts @@ -3,7 +3,7 @@ import { TestBed } from '@angular/core/testing'; import { vi, test, expect, afterEach } from 'vitest'; import { of, BehaviorSubject } from 'rxjs'; import { debounceTime, switchMap, map, startWith } from 'rxjs/operators'; -import { render, screen, waitFor, waitForElementToBeRemoved, within } from '../lib/testing-library'; +import { render, screen, waitForElementToBeRemoved, within } from '../lib/testing-library'; import userEvent from '@testing-library/user-event'; import { AsyncPipe, NgForOf } from '@angular/common'; @@ -98,7 +98,9 @@ afterEach(() => { async function setup() { vi.useFakeTimers(); - const user = userEvent.setup(); + const user = userEvent.setup({ + advanceTimers: vi.advanceTimersByTime, + }); await render(EntitiesComponent, { providers: [ @@ -139,7 +141,7 @@ test('renders the entities', async () => { expect(await screen.findByRole('cell', { name: /Entity 3/i })).toBeInTheDocument(); }); -test.skip('finds the cell', async () => { +test('finds the cell', async () => { const { user } = await setup(); await user.type(await screen.findByRole('textbox', { name: /Search entities/i }), 'Entity 2', {}); @@ -150,9 +152,10 @@ test.skip('finds the cell', async () => { expect(await screen.findByRole('cell', { name: /Entity 2/i })).toBeInTheDocument(); }); -test.skip('opens the modal', async () => { +test('opens the modal', async () => { const { modalMock, user } = await setup(); - await user.click(await screen.findByRole('button', { name: /New Entity/i })); + + await user.click(await screen.findByRole('button', { name: /Create New Entity/i })); expect(modalMock.open).toHaveBeenCalledWith('new entity'); const row = await screen.findByRole('row', { @@ -164,5 +167,6 @@ test.skip('opens the modal', async () => { name: /edit/i, }), ); - await waitFor(() => expect(modalMock.open).toHaveBeenCalledWith('edit entity', 'Entity 2')); + + await vi.waitFor(() => expect(modalMock.open).toHaveBeenCalledWith('edit entity', 'Entity 2')); });