From ef6194b134c64c9249f9f3614ca7dad0bd275ec5 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:26:55 +0200 Subject: [PATCH 01/12] docs: include v16 in version compatibility table (#448) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eed18ab..531c5e5 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ You may also be interested in installing `jest-dom` so you can use | Angular | Angular Testing Library | | ------- | ----------------------- | -| 17.x | 15.x, 14.x, 13.x | +| 17.x | 16.x, 15.x, 14.x, 13.x | | 16.x | 14.x, 13.x | | >= 15.1 | 14.x, 13.x | | < 15.1 | 12.x, 11.x | From 3d396c0d925122159b750b6cd363c13b8efeb07a Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Mon, 20 May 2024 14:24:58 +0200 Subject: [PATCH 02/12] docs: add directive example (#450) --- .../src/app/examples/08-directive.spec.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/example-app/src/app/examples/08-directive.spec.ts b/apps/example-app/src/app/examples/08-directive.spec.ts index 5ba450b..8b70b38 100644 --- a/apps/example-app/src/app/examples/08-directive.spec.ts +++ b/apps/example-app/src/app/examples/08-directive.spec.ts @@ -1,8 +1,34 @@ +import { Component } from '@angular/core'; import { render, screen } from '@testing-library/angular'; import userEvent from '@testing-library/user-event'; import { SpoilerDirective } from './08-directive'; +test('it is possible to test directives with container component', async () => { + @Component({ + template: `
`, + imports: [SpoilerDirective], + standalone: true, + }) + class FixtureComponent {} + + const user = userEvent.setup(); + await render(FixtureComponent); + + const directive = screen.getByTestId('dir'); + + expect(screen.queryByText('I am visible now...')).not.toBeInTheDocument(); + expect(screen.getByText('SPOILER')).toBeInTheDocument(); + + await user.hover(directive); + expect(screen.queryByText('SPOILER')).not.toBeInTheDocument(); + expect(screen.getByText('I am visible now...')).toBeInTheDocument(); + + await user.unhover(directive); + expect(screen.getByText('SPOILER')).toBeInTheDocument(); + expect(screen.queryByText('I am visible now...')).not.toBeInTheDocument(); +}); + test('it is possible to test directives', async () => { const user = userEvent.setup(); From 9a1da54a31fb062e8d38385eb300323a11a903ad Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 25 May 2024 18:08:08 +0200 Subject: [PATCH 03/12] build: update to Angular 18 --- .eslintrc.json | 10 +++- .github/workflows/ci.yml | 2 +- apps/example-app-karma/project.json | 7 ++- apps/example-app/project.json | 7 ++- decorate-angular-cli.js | 70 ------------------------ nx.json | 15 +++--- package.json | 76 +++++++++++++-------------- projects/testing-library/project.json | 7 ++- 8 files changed, 63 insertions(+), 131 deletions(-) delete mode 100644 decorate-angular-cli.js diff --git a/.eslintrc.json b/.eslintrc.json index 765bf88..0a96094 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -24,12 +24,18 @@ { "files": ["*.ts", "*.tsx"], "extends": ["plugin:@nx/typescript"], - "rules": {} + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off" + } }, { "files": ["*.js", "*.jsx"], "extends": ["plugin:@nx/javascript"], - "rules": {} + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off" + } }, { "files": ["*.ts"], diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28aac0d..5820814 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - name: install - run: npm install + run: npm install --force - name: build run: npm run build -- --skip-nx-cache - name: test diff --git a/apps/example-app-karma/project.json b/apps/example-app-karma/project.json index 733fe68..00820e3 100644 --- a/apps/example-app-karma/project.json +++ b/apps/example-app-karma/project.json @@ -4,6 +4,7 @@ "projectType": "application", "sourceRoot": "apps/example-app-karma/src", "prefix": "app", + "tags": [], "generators": {}, "targets": { "build": { @@ -52,8 +53,7 @@ "defaultConfiguration": "development" }, "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"] + "executor": "@nx/eslint:lint" }, "test": { "executor": "@angular-devkit/build-angular:karma", @@ -63,6 +63,5 @@ "karmaConfig": "apps/example-app-karma/karma.conf.js" } } - }, - "tags": [] + } } diff --git a/apps/example-app/project.json b/apps/example-app/project.json index 8af5697..ecbadfc 100644 --- a/apps/example-app/project.json +++ b/apps/example-app/project.json @@ -4,6 +4,7 @@ "projectType": "application", "sourceRoot": "apps/example-app/src", "prefix": "app", + "tags": [], "generators": {}, "targets": { "build": { @@ -59,8 +60,7 @@ } }, "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"] + "executor": "@nx/eslint:lint" }, "test": { "executor": "@nx/jest:jest", @@ -70,6 +70,5 @@ }, "outputs": ["{workspaceRoot}/coverage/"] } - }, - "tags": [] + } } diff --git a/decorate-angular-cli.js b/decorate-angular-cli.js deleted file mode 100644 index cff5ab7..0000000 --- a/decorate-angular-cli.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching - * and faster execution of tasks. - * - * It does this by: - * - * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. - * - Symlinking the ng to nx command, so all commands run through the Nx CLI - * - Updating the package.json postinstall script to give you control over this script - * - * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. - * Every command you run should work the same when using the Nx CLI, except faster. - * - * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, - * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. - * The Nx CLI simply does some optimizations before invoking the Angular CLI. - * - * To opt out of this patch: - * - Replace occurrences of nx with ng in your package.json - * - Remove the script from your postinstall script in your package.json - * - Delete and reinstall your node_modules - */ - -const fs = require('fs'); -const os = require('os'); -const cp = require('child_process'); -const isWindows = os.platform() === 'win32'; -let output; -try { - output = require('@nx/workspace').output; -} catch (e) { - console.warn( - 'Angular CLI could not be decorated to enable computation caching. Please ensure @nx/workspace is installed.', - ); - process.exit(0); -} - -/** - * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still - * invoke the Nx CLI and get the benefits of computation caching. - */ -function symlinkNgCLItoNxCLI() { - try { - const ngPath = './node_modules/.bin/ng'; - const nxPath = './node_modules/.bin/nx'; - if (isWindows) { - /** - * This is the most reliable way to create symlink-like behavior on Windows. - * Such that it works in all shells and works with npx. - */ - ['', '.cmd', '.ps1'].forEach((ext) => { - if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); - }); - } else { - // If unix-based, symlink - cp.execSync(`ln -sf ./nx ${ngPath}`); - } - } catch (e) { - output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message }); - throw e; - } -} - -try { - symlinkNgCLItoNxCLI(); - require('@nrwl/cli/lib/decorate-cli').decorateCli(); - output.log({ title: 'Angular CLI has been decorated to enable computation caching.' }); -} catch (e) { - output.error({ title: 'Decoration of the Angular CLI did not complete successfully' }); -} diff --git a/nx.json b/nx.json index 7040d68..df534f7 100644 --- a/nx.json +++ b/nx.json @@ -1,7 +1,4 @@ { - "affected": { - "defaultBase": "main" - }, "workspaceLayout": { "appsDir": "apps", "libsDir": "projects" @@ -71,10 +68,6 @@ "inputs": ["default", "^production"], "cache": true }, - "lint": { - "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], - "cache": true - }, "@nx/jest:jest": { "inputs": ["default", "^production"], "cache": true, @@ -87,6 +80,10 @@ "codeCoverage": true } } + }, + "@nx/eslint:lint": { + "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], + "cache": true } }, "namedInputs": { @@ -104,5 +101,7 @@ ] }, "nxCloudAccessToken": "M2Q4YjlkNjMtMzY1NC00ZjkwLTk1ZjgtZjg5Y2VkMzFjM2FifHJlYWQtd3JpdGU=", - "parallel": 3 + "parallel": 3, + "useInferencePlugins": false, + "defaultBase": "main" } diff --git a/package.json b/package.json index 6c96abe..235d0ec 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "scripts": { "ng": "nx", "nx": "nx", - "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2020 browser module main", "start": "nx serve", "prebuild": "rimraf dist", "build": "nx run-many --target=build --projects=testing-library", @@ -28,42 +27,42 @@ "prepare": "git config core.hookspath .githooks" }, "dependencies": { - "@angular/animations": "17.3.2", - "@angular/cdk": "17.3.2", - "@angular/common": "17.3.2", - "@angular/compiler": "17.3.2", - "@angular/core": "17.3.2", - "@angular/material": "17.3.2", - "@angular/platform-browser": "17.3.2", - "@angular/platform-browser-dynamic": "17.3.2", - "@angular/router": "17.3.2", - "@ngrx/store": "17.1.0", - "@nx/angular": "17.2.8", + "@angular/animations": "18.0.0", + "@angular/cdk": "18.0.0", + "@angular/common": "18.0.0", + "@angular/compiler": "18.0.0", + "@angular/core": "18.0.0", + "@angular/material": "18.0.0", + "@angular/platform-browser": "18.0.0", + "@angular/platform-browser-dynamic": "18.0.0", + "@angular/router": "18.0.0", + "@ngrx/store": "18.0.0-beta.1", + "@nx/angular": "19.1.0", "@testing-library/dom": "^10.0.0", "rxjs": "7.8.0", "tslib": "~2.3.1", "zone.js": "0.14.2" }, "devDependencies": { - "@angular-devkit/build-angular": "17.3.2", - "@angular-devkit/core": "17.3.2", - "@angular-devkit/schematics": "17.3.2", - "@angular-eslint/builder": "17.0.1", - "@angular-eslint/eslint-plugin": "17.0.1", - "@angular-eslint/eslint-plugin-template": "17.0.1", - "@angular-eslint/schematics": "17.0.1", - "@angular-eslint/template-parser": "17.0.1", - "@angular/cli": "~17.3.2", - "@angular/compiler-cli": "17.3.2", - "@angular/forms": "17.3.2", - "@angular/language-service": "17.3.2", - "@nx/eslint": "17.2.8", - "@nx/eslint-plugin": "17.2.8", - "@nx/jest": "17.2.8", - "@nx/node": "17.2.8", - "@nx/plugin": "17.2.8", - "@nx/workspace": "17.2.8", - "@schematics/angular": "17.3.2", + "@angular-devkit/build-angular": "18.0.1", + "@angular-devkit/core": "18.0.1", + "@angular-devkit/schematics": "18.0.1", + "@angular-eslint/builder": "17.3.0", + "@angular-eslint/eslint-plugin": "17.3.0", + "@angular-eslint/eslint-plugin-template": "17.3.0", + "@angular-eslint/schematics": "17.5.1", + "@angular-eslint/template-parser": "17.3.0", + "@angular/cli": "~18.0.0", + "@angular/compiler-cli": "18.0.0", + "@angular/forms": "18.0.0", + "@angular/language-service": "18.0.0", + "@nx/eslint": "19.1.0", + "@nx/eslint-plugin": "19.1.0", + "@nx/jest": "19.1.0", + "@nx/node": "19.1.0", + "@nx/plugin": "19.1.0", + "@nx/workspace": "19.1.0", + "@schematics/angular": "18.0.1", "@testing-library/jasmine-dom": "^1.2.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/user-event": "^14.4.3", @@ -71,10 +70,11 @@ "@types/jest": "29.5.1", "@types/node": "18.16.9", "@types/testing-library__jasmine-dom": "^1.3.0", - "@typescript-eslint/eslint-plugin": "6.9.1", - "@typescript-eslint/parser": "6.9.1", + "@typescript-eslint/eslint-plugin": "7.3.0", + "@typescript-eslint/parser": "7.3.0", + "autoprefixer": "^10.4.0", "cpy-cli": "^3.1.1", - "eslint": "8.48.0", + "eslint": "8.57.0", "eslint-config-prettier": "9.0.0", "eslint-plugin-import": "~2.25.4", "eslint-plugin-jasmine": "~4.1.3", @@ -85,7 +85,7 @@ "jasmine-spec-reporter": "7.0.0", "jest": "29.7.0", "jest-environment-jsdom": "29.5.0", - "jest-preset-angular": "14.0.3", + "jest-preset-angular": "14.1.0", "karma": "6.4.0", "karma-chrome-launcher": "^3.1.0", "karma-coverage": "^2.2.1", @@ -93,8 +93,8 @@ "karma-jasmine-html-reporter": "2.0.0", "lint-staged": "^12.1.6", "ng-mocks": "^14.11.0", - "ng-packagr": "17.3.0", - "nx": "17.2.8", + "ng-packagr": "18.0.0", + "nx": "19.1.0", "postcss": "^8.4.5", "postcss-import": "14.1.0", "postcss-preset-env": "7.5.0", @@ -104,6 +104,6 @@ "semantic-release": "^18.0.0", "ts-jest": "29.1.0", "ts-node": "10.9.1", - "typescript": "5.2.2" + "typescript": "5.4.5" } } diff --git a/projects/testing-library/project.json b/projects/testing-library/project.json index b91e85c..1deb065 100644 --- a/projects/testing-library/project.json +++ b/projects/testing-library/project.json @@ -4,6 +4,7 @@ "projectType": "library", "sourceRoot": "projects/testing-library/src", "prefix": "lib", + "tags": [], "targets": { "build-package": { "executor": "@nx/angular:package", @@ -22,8 +23,7 @@ "defaultConfiguration": "production" }, "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"] + "executor": "@nx/eslint:lint" }, "build": { "executor": "nx:run-commands", @@ -50,6 +50,5 @@ }, "outputs": ["{workspaceRoot}/coverage/projects/testing-library"] } - }, - "tags": [] + } } From 7281dec47c6e517566413fe33bff449cfdd7197a Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 25 May 2024 18:08:30 +0200 Subject: [PATCH 04/12] docs: update version compatibility --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 531c5e5..e923e57 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,7 @@ You may also be interested in installing `jest-dom` so you can use | Angular | Angular Testing Library | | ------- | ----------------------- | +| 18.x | 16.x, 15.x, 14.x, 13.x | | 17.x | 16.x, 15.x, 14.x, 13.x | | 16.x | 14.x, 13.x | | >= 15.1 | 14.x, 13.x | From 47f680f18f1536e52e48c89bf371ba596e1a64db Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Sat, 1 Jun 2024 20:07:18 +0300 Subject: [PATCH 05/12] docs: update all contributors badge (#452) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e923e57..2ba3f84 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/github/all-contributors/testing-library/angular-testing-library?color=ee8449&style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Discord][discord-badge]][discord] From 86c08e066df2bb316f405cf49e5c27effc60d6e0 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 21 Jun 2024 20:27:32 +0200 Subject: [PATCH 06/12] docs: add computed example (#455) --- .../22-signal-inputs.component.spec.ts | 50 +++++++++++++++---- .../examples/22-signal-inputs.component.ts | 7 ++- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts b/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts index 6a55e61..113d330 100644 --- a/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts +++ b/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/angular'; +import { render, screen, within } from '@testing-library/angular'; import { SignalInputComponent } from './22-signal-inputs.component'; import userEvent from '@testing-library/user-event'; @@ -10,7 +10,20 @@ test('works with signal inputs', async () => { }, }); - expect(screen.getByText(/hello world/i)).toBeInTheDocument(); + const inputValue = within(screen.getByTestId('input-value')); + expect(inputValue.getByText(/hello world/i)).toBeInTheDocument(); +}); + +test('works with computed', async () => { + await render(SignalInputComponent, { + componentInputs: { + greeting: 'Hello', + name: 'world', + }, + }); + + const computedValue = within(screen.getByTestId('computed-value')); + expect(computedValue.getByText(/hello world/i)).toBeInTheDocument(); }); test('can update signal inputs', async () => { @@ -21,11 +34,16 @@ test('can update signal inputs', async () => { }, }); - expect(screen.getByText(/hello world/i)).toBeInTheDocument(); + const inputValue = within(screen.getByTestId('input-value')); + const computedValue = within(screen.getByTestId('computed-value')); + + expect(inputValue.getByText(/hello world/i)).toBeInTheDocument(); fixture.componentInstance.name.set('updated'); // set doesn't trigger change detection within the test, findBy is needed to update the template - expect(await screen.findByText(/hello updated/i)).toBeInTheDocument(); + expect(await inputValue.findByText(/hello updated/i)).toBeInTheDocument(); + expect(await computedValue.findByText(/hello updated/i)).toBeInTheDocument(); + // it's not recommended to access the model directly, but it's possible expect(fixture.componentInstance.name()).toBe('updated'); }); @@ -55,22 +73,29 @@ test('model update also updates the template', async () => { }, }); - expect(screen.getByText(/hello initial/i)).toBeInTheDocument(); + const inputValue = within(screen.getByTestId('input-value')); + const computedValue = within(screen.getByTestId('computed-value')); + + expect(inputValue.getByText(/hello initial/i)).toBeInTheDocument(); + expect(computedValue.getByText(/hello initial/i)).toBeInTheDocument(); await userEvent.clear(screen.getByRole('textbox')); await userEvent.type(screen.getByRole('textbox'), 'updated'); - expect(screen.getByText(/hello updated/i)).toBeInTheDocument(); + expect(inputValue.getByText(/hello updated/i)).toBeInTheDocument(); + expect(computedValue.getByText(/hello updated/i)).toBeInTheDocument(); expect(fixture.componentInstance.name()).toBe('updated'); fixture.componentInstance.name.set('new value'); // set doesn't trigger change detection within the test, findBy is needed to update the template - expect(await screen.findByText(/hello new value/i)).toBeInTheDocument(); + expect(await inputValue.findByText(/hello new value/i)).toBeInTheDocument(); + expect(await computedValue.findByText(/hello new value/i)).toBeInTheDocument(); + // it's not recommended to access the model directly, but it's possible expect(fixture.componentInstance.name()).toBe('new value'); }); -test('works with signal inputs and rerenders', async () => { +test('works with signal inputs, computed values, and rerenders', async () => { const view = await render(SignalInputComponent, { componentInputs: { greeting: 'Hello', @@ -78,7 +103,11 @@ test('works with signal inputs and rerenders', async () => { }, }); - expect(screen.getByText(/hello world/i)).toBeInTheDocument(); + const inputValue = within(screen.getByTestId('input-value')); + const computedValue = within(screen.getByTestId('computed-value')); + + expect(inputValue.getByText(/hello world/i)).toBeInTheDocument(); + expect(computedValue.getByText(/hello world/i)).toBeInTheDocument(); await view.rerender({ componentInputs: { @@ -87,5 +116,6 @@ test('works with signal inputs and rerenders', async () => { }, }); - expect(screen.getByText(/bye test/i)).toBeInTheDocument(); + expect(inputValue.getByText(/bye test/i)).toBeInTheDocument(); + expect(computedValue.getByText(/bye test/i)).toBeInTheDocument(); }); diff --git a/apps/example-app/src/app/examples/22-signal-inputs.component.ts b/apps/example-app/src/app/examples/22-signal-inputs.component.ts index ae1e779..ddc0c90 100644 --- a/apps/example-app/src/app/examples/22-signal-inputs.component.ts +++ b/apps/example-app/src/app/examples/22-signal-inputs.component.ts @@ -1,10 +1,11 @@ -import { Component, input, model, output } from '@angular/core'; +import { Component, computed, input, model, output } from '@angular/core'; import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-signal-input', template: ` -
{{ greetings() }} {{ name() }}
+
{{ greetings() }} {{ name() }}
+
{{ greetingMessage() }}
`, @@ -18,6 +19,8 @@ export class SignalInputComponent { name = model.required(); submit = output(); + greetingMessage = computed(() => `${this.greetings()} ${this.name()}`); + submitName() { this.submit.emit(this.name()); } From fbfc9dbe1ca97ac519428bf6cfb15118f2a7d059 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 21 Jun 2024 18:51:25 +0200 Subject: [PATCH 07/12] feat: move dtl to peerDeps (#456) BREAKING CHANGE: `@testing-library/dom` is now a peer dependency of `@testing-library/angular`. This means that you need to install `@testing-library/dom` separately. --- projects/testing-library/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json index fd3cfac..4aea894 100644 --- a/projects/testing-library/package.json +++ b/projects/testing-library/package.json @@ -32,10 +32,10 @@ "@angular/common": ">= 17.0.0", "@angular/platform-browser": ">= 17.0.0", "@angular/router": ">= 17.0.0", - "@angular/core": ">= 17.0.0" + "@angular/core": ">= 17.0.0", + "@testing-library/dom": "^10.0.0" }, "dependencies": { - "@testing-library/dom": "^10.0.0", "tslib": "^2.3.1" }, "publishConfig": { From 5d7b368d273b2952bc2dc222cf0bb6eac5f2c598 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 21 Jun 2024 19:59:34 +0200 Subject: [PATCH 08/12] feat: add DTL as devDependency on ng-add (#457) --- .../schematics/ng-add/index.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/projects/testing-library/schematics/ng-add/index.ts b/projects/testing-library/schematics/ng-add/index.ts index 68b9dfa..24a0a3d 100644 --- a/projects/testing-library/schematics/ng-add/index.ts +++ b/projects/testing-library/schematics/ng-add/index.ts @@ -1,11 +1,27 @@ import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { + addPackageJsonDependency, + getPackageJsonDependency, + NodeDependencyType, +} from '@schematics/angular/utility/dependencies'; + +const dtl = '@testing-library/dom'; export default function (): Rule { - return (host: Tree, context: SchematicContext) => { + return (tree: Tree, context: SchematicContext) => { + const dtlDep = getPackageJsonDependency(tree, dtl); + if (dtlDep) { + context.logger.info(`Skipping installation of '@testing-library/dom' because it's already installed.`); + } else { + context.logger.info(`Adding '@testing-library/dom' as a dev dependency.`); + addPackageJsonDependency(tree, { name: dtl, type: NodeDependencyType.Dev, overwrite: false, version: '^10.0.0' }); + } + context.logger.info( `Correctly installed @testing-library/angular. See our docs at https://testing-library.com/docs/angular-testing-library/intro/ to get started.`, ); - return host; + + return tree; }; } From 563d44b65dc8d02855f24b3d2fa88866970b58f6 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 21 Jun 2024 20:11:36 +0200 Subject: [PATCH 09/12] feat: add migration to add DTL as devDependency (#458) --- projects/testing-library/package.json | 2 +- .../dtl-as-dev-dependency/index.spec.ts | 44 +++++++++++++++++++ .../migrations/dtl-as-dev-dependency/index.ts | 20 +++++++++ .../schematics/migrations/migration.json | 3 -- .../schematics/migrations/migrations.json | 10 +++++ projects/testing-library/test-setup.ts | 4 ++ .../testing-library/tsconfig.lib.prod.json | 2 +- .../testing-library/tsconfig.schematics.json | 3 +- 8 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.spec.ts create mode 100644 projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.ts delete mode 100644 projects/testing-library/schematics/migrations/migration.json create mode 100644 projects/testing-library/schematics/migrations/migrations.json diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json index 4aea894..2852d02 100644 --- a/projects/testing-library/package.json +++ b/projects/testing-library/package.json @@ -26,7 +26,7 @@ "save": "devDependencies" }, "ng-update": { - "migrations": "./schematics/migrations/migration.json" + "migrations": "./schematics/migrations/migrations.json" }, "peerDependencies": { "@angular/common": ">= 17.0.0", diff --git a/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.spec.ts b/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.spec.ts new file mode 100644 index 0000000..a3c0fd1 --- /dev/null +++ b/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.spec.ts @@ -0,0 +1,44 @@ +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import * as path from 'path'; +import { EmptyTree } from '@angular-devkit/schematics'; + +test('adds DTL to devDependencies', async () => { + const tree = await setup({}); + const pkg = tree.readContent('package.json'); + + expect(pkg).toMatchInlineSnapshot(` + "{ + \\"devDependencies\\": { + \\"@testing-library/dom\\": \\"^10.0.0\\" + } + }" + `); +}); + +test('ignores if DTL is already listed as a dev dependency', async () => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const tree = await setup({ devDependencies: { '@testing-library/dom': '^9.0.0' } }); + const pkg = tree.readContent('package.json'); + + expect(pkg).toMatchInlineSnapshot(`"{\\"devDependencies\\":{\\"@testing-library/dom\\":\\"^9.0.0\\"}}"`); +}); + +test('ignores if DTL is already listed as a dependency', async () => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const tree = await setup({ dependencies: { '@testing-library/dom': '^11.0.0' } }); + const pkg = tree.readContent('package.json'); + + expect(pkg).toMatchInlineSnapshot(`"{\\"dependencies\\":{\\"@testing-library/dom\\":\\"^11.0.0\\"}}"`); +}); + +async function setup(packageJson: object) { + const collectionPath = path.join(__dirname, '../migrations.json'); + const schematicRunner = new SchematicTestRunner('schematics', collectionPath); + + const tree = new UnitTestTree(new EmptyTree()); + tree.create('package.json', JSON.stringify(packageJson)); + + await schematicRunner.runSchematic(`atl-add-dtl-as-dev-dependency`, {}, tree); + + return tree; +} diff --git a/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.ts b/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.ts new file mode 100644 index 0000000..1c06e2f --- /dev/null +++ b/projects/testing-library/schematics/migrations/dtl-as-dev-dependency/index.ts @@ -0,0 +1,20 @@ +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { + addPackageJsonDependency, + getPackageJsonDependency, + NodeDependencyType, +} from '@schematics/angular/utility/dependencies'; + +const dtl = '@testing-library/dom'; + +export default function (): Rule { + return async (tree: Tree, context: SchematicContext) => { + const dtlDep = getPackageJsonDependency(tree, dtl); + if (dtlDep) { + context.logger.info(`Skipping installation of '@testing-library/dom' because it's already installed.`); + } else { + context.logger.info(`Adding '@testing-library/dom' as a peer dependency.`); + addPackageJsonDependency(tree, { name: dtl, type: NodeDependencyType.Dev, overwrite: false, version: '^10.0.0' }); + } + }; +} diff --git a/projects/testing-library/schematics/migrations/migration.json b/projects/testing-library/schematics/migrations/migration.json deleted file mode 100644 index 63001b4..0000000 --- a/projects/testing-library/schematics/migrations/migration.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "schematics": {} -} diff --git a/projects/testing-library/schematics/migrations/migrations.json b/projects/testing-library/schematics/migrations/migrations.json new file mode 100644 index 0000000..711b7ae --- /dev/null +++ b/projects/testing-library/schematics/migrations/migrations.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "atl-add-dtl-as-dev-dependency": { + "description": "Add @testing-library/dom as a dev dependency", + "version": "17.0.0-beta.3", + "factory": "./dtl-as-dev-dependency/index" + } + } +} diff --git a/projects/testing-library/test-setup.ts b/projects/testing-library/test-setup.ts index 0da94a0..600d085 100644 --- a/projects/testing-library/test-setup.ts +++ b/projects/testing-library/test-setup.ts @@ -1,2 +1,6 @@ import 'jest-preset-angular/setup-jest'; import '@testing-library/jest-dom'; +import { TextEncoder, TextDecoder } from 'util'; + +// eslint-disable-next-line @typescript-eslint/naming-convention +Object.assign(global, { TextDecoder, TextEncoder }); diff --git a/projects/testing-library/tsconfig.lib.prod.json b/projects/testing-library/tsconfig.lib.prod.json index 1f041c9..752ed5e 100644 --- a/projects/testing-library/tsconfig.lib.prod.json +++ b/projects/testing-library/tsconfig.lib.prod.json @@ -8,5 +8,5 @@ "angularCompilerOptions": { "compilationMode": "partial" }, - "exclude": ["jest.config.ts"] + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"] } diff --git a/projects/testing-library/tsconfig.schematics.json b/projects/testing-library/tsconfig.schematics.json index 481a34b..1311558 100644 --- a/projects/testing-library/tsconfig.schematics.json +++ b/projects/testing-library/tsconfig.schematics.json @@ -13,5 +13,6 @@ "skipLibCheck": true, "sourceMap": false }, - "include": ["schematics/**/*.ts"] + "include": ["schematics/**/*.ts"], + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"] } From af03c484b377631a9a6c0f8b48f31f08cdd89869 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 22 Jun 2024 14:22:42 +0200 Subject: [PATCH 10/12] docs: update docs for v17 (#459) --- README.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2ba3f84..7ab5040 100644 --- a/README.md +++ b/README.md @@ -147,10 +147,18 @@ describe('Counter', () => { ## Installation This module is distributed via [npm][npm] which is bundled with [node][node] and -should be installed as one of your project's `devDependencies`: +should be installed as one of your project's `devDependencies`. +Starting from ATL version 17, you'll also need to install `@testing-library/dom`: ```bash -npm install @testing-library/angular --save-dev +npm install --save-dev @testing-library/angular @testing-library/dom +``` + +Or, you can use the `ng add` command. +This includes the installation of `@testing-library/dom`. + +```bash +ng add @testing-library/angular ``` You may also be interested in installing `jest-dom` so you can use @@ -160,14 +168,14 @@ You may also be interested in installing `jest-dom` so you can use ## Version compatibility -| Angular | Angular Testing Library | -| ------- | ----------------------- | -| 18.x | 16.x, 15.x, 14.x, 13.x | -| 17.x | 16.x, 15.x, 14.x, 13.x | -| 16.x | 14.x, 13.x | -| >= 15.1 | 14.x, 13.x | -| < 15.1 | 12.x, 11.x | -| 14.x | 12.x, 11.x | +| Angular | Angular Testing Library | +| ------- | ---------------------------- | +| 18.x | 17.x, 16.x, 15.x, 14.x, 13.x | +| 17.x | 17.x, 16.x, 15.x, 14.x, 13.x | +| 16.x | 14.x, 13.x | +| >= 15.1 | 14.x, 13.x | +| < 15.1 | 12.x, 11.x | +| 14.x | 12.x, 11.x | ## Guiding Principles From 68e6b84cf0b61e79fc74a5b3afedbcc5b9e5e785 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 22 Jun 2024 15:20:44 +0200 Subject: [PATCH 11/12] fix: schematics output folder (#461) --- projects/testing-library/tsconfig.schematics.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/testing-library/tsconfig.schematics.json b/projects/testing-library/tsconfig.schematics.json index 1311558..c011851 100644 --- a/projects/testing-library/tsconfig.schematics.json +++ b/projects/testing-library/tsconfig.schematics.json @@ -8,7 +8,7 @@ "esModuleInterop": true, "resolveJsonModule": true, "forceConsistentCasingInFileNames": true, - "outDir": "../../dist/@testing-library/angular/schematics/ng-add", + "outDir": "../../dist/@testing-library/angular/schematics", "removeComments": true, "skipLibCheck": true, "sourceMap": false From 0652a14973f3a610e52ae9f67b0cb16148bb5ddf Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Mon, 24 Jun 2024 15:40:37 +0200 Subject: [PATCH 12/12] docs: reword installation steps (#463) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ab5040..ce2e906 100644 --- a/README.md +++ b/README.md @@ -148,14 +148,14 @@ describe('Counter', () => { This module is distributed via [npm][npm] which is bundled with [node][node] and should be installed as one of your project's `devDependencies`. -Starting from ATL version 17, you'll also need to install `@testing-library/dom`: +Starting from ATL version 17, you also need to install `@testing-library/dom`: ```bash npm install --save-dev @testing-library/angular @testing-library/dom ``` Or, you can use the `ng add` command. -This includes the installation of `@testing-library/dom`. +This sets up your project to use Angular Testing Library, which also includes the installation of `@testing-library/dom`. ```bash ng add @testing-library/angular