diff --git a/.all-contributorsrc b/.all-contributorsrc index 6ebf8030..9c215474 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,7 +1,5 @@ { - "files": [ - "README.md" - ], + "files": ["README.md"], "imageSize": 100, "commit": false, "contributors": [ @@ -10,507 +8,371 @@ "name": "Tim Deschryver", "avatar_url": "https://avatars1.githubusercontent.com/u/28659384?v=4", "profile": "http://timdeschryver.dev", - "contributions": [ - "code", - "doc", - "infra", - "test" - ] + "contributions": ["code", "doc", "infra", "test"] }, { "login": "MichaelDeBoey", "name": "Michaël De Boey", "avatar_url": "https://avatars3.githubusercontent.com/u/6643991?v=4", "profile": "https://michaeldeboey.be", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "flakolefluk", "name": "Ignacio Le Fluk", "avatar_url": "https://avatars0.githubusercontent.com/u/11986564?v=4", "profile": "https://github.com/flakolefluk", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "szabototo89", "name": "Tamás Szabó", "avatar_url": "https://avatars0.githubusercontent.com/u/3720079?v=4", "profile": "https://hu.linkedin.com/pub/tamas-szabo/57/a4b/242", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "GregOnNet", "name": "Gregor Woiwode", "avatar_url": "https://avatars3.githubusercontent.com/u/444278?v=4", "profile": "https://medium.com/@gregor.woiwode", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "tonivj5", "name": "Toni Villena", "avatar_url": "https://avatars2.githubusercontent.com/u/7110786?v=4", "profile": "https://github.com/tonivj5", - "contributions": [ - "bug", - "code", - "doc", - "test" - ] + "contributions": ["bug", "code", "doc", "test"] }, { "login": "ShPelles", "name": "ShPelles", "avatar_url": "https://avatars0.githubusercontent.com/u/43875468?v=4", "profile": "https://github.com/ShPelles", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "miluoshi", "name": "Miluoshi", "avatar_url": "https://avatars1.githubusercontent.com/u/1130547?v=4", "profile": "https://github.com/miluoshi", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "nickmccurdy", "name": "Nick McCurdy", "avatar_url": "https://avatars0.githubusercontent.com/u/927220?v=4", "profile": "https://nickmccurdy.com/", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "SrinivasanTarget", "name": "Srinivasan Sekar", "avatar_url": "https://avatars2.githubusercontent.com/u/8896549?v=4", "profile": "https://github.com/SrinivasanTarget", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "SerkanSipahi", "name": "Bitcollage", "avatar_url": "https://avatars2.githubusercontent.com/u/1880749?v=4", "profile": "https://www.linkedin.com/in/serkan-sipahi-59b20081/", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "krokofant", "name": "Emil Sundin", "avatar_url": "https://avatars0.githubusercontent.com/u/5908498?v=4", "profile": "https://github.com/krokofant", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "Ombrax", "name": "Ombrax", "avatar_url": "https://avatars0.githubusercontent.com/u/7486723?v=4", "profile": "https://github.com/Ombrax", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "rafaelss95", "name": "Rafael Santana", "avatar_url": "https://avatars0.githubusercontent.com/u/11965907?v=4", "profile": "https://github.com/rafaelss95", - "contributions": [ - "code", - "test", - "bug" - ] + "contributions": ["code", "test", "bug"] }, { "login": "BBlackwo", "name": "Benjamin Blackwood", "avatar_url": "https://avatars0.githubusercontent.com/u/7598058?v=4", "profile": "https://twitter.com/B_Blackwo", - "contributions": [ - "doc", - "test" - ] + "contributions": ["doc", "test"] }, { "login": "portothree", "name": "Gustavo Porto", "avatar_url": "https://avatars2.githubusercontent.com/u/3718120?v=4", "profile": "http://gustavoporto.dev", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "bovandersteene", "name": "Bo Vandersteene", "avatar_url": "https://avatars1.githubusercontent.com/u/1673799?v=4", "profile": "http://wwww.reibo.be", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "jbchr", "name": "Janek", "avatar_url": "https://avatars1.githubusercontent.com/u/23141806?v=4", "profile": "https://github.com/jbchr", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "GlebIrovich", "name": "Gleb Irovich", "avatar_url": "https://avatars.githubusercontent.com/u/33176414?v=4", "profile": "https://github.com/GlebIrovich", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "the-ult", "name": "Arjen", "avatar_url": "https://avatars.githubusercontent.com/u/4863062?v=4", "profile": "https://github.com/the-ult", - "contributions": [ - "code", - "maintenance" - ] + "contributions": ["code", "maintenance"] }, { "login": "lacolaco", "name": "Suguru Inatomi", "avatar_url": "https://avatars.githubusercontent.com/u/1529180?v=4", "profile": "https://lacolaco.net", - "contributions": [ - "code", - "ideas" - ] + "contributions": ["code", "ideas"] }, { "login": "amitmiran137", "name": "Amit Miran", "avatar_url": "https://avatars.githubusercontent.com/u/47772523?v=4", "profile": "https://github.com/amitmiran137", - "contributions": [ - "infra" - ] + "contributions": ["infra"] }, { "login": "jwillebrands", "name": "Jan-Willem Willebrands", "avatar_url": "https://avatars.githubusercontent.com/u/8925?v=4", "profile": "https://github.com/jwillebrands", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "rothsandro", "name": "Sandro", "avatar_url": "https://avatars.githubusercontent.com/u/16229645?v=4", "profile": "https://www.sandroroth.com", - "contributions": [ - "code", - "bug" - ] + "contributions": ["code", "bug"] }, { "login": "michaelwestphal", "name": "Michael Westphal", "avatar_url": "https://avatars.githubusercontent.com/u/1829174?v=4", "profile": "https://github.com/michaelwestphal", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "Lukas-Kullmann", "name": "Lukas", "avatar_url": "https://avatars.githubusercontent.com/u/387547?v=4", "profile": "https://github.com/Lukas-Kullmann", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "MatanBobi", "name": "Matan Borenkraout", "avatar_url": "https://avatars.githubusercontent.com/u/12711091?v=4", "profile": "https://matan.io", - "contributions": [ - "maintenance" - ] + "contributions": ["maintenance"] }, { "login": "mleimer", "name": "mleimer", "avatar_url": "https://avatars.githubusercontent.com/u/14271564?v=4", "profile": "https://github.com/mleimer", - "contributions": [ - "doc", - "test" - ] + "contributions": ["doc", "test"] }, { "login": "meirka", "name": "MeIr", "avatar_url": "https://avatars.githubusercontent.com/u/750901?v=4", "profile": "https://github.com/meirka", - "contributions": [ - "bug", - "test" - ] + "contributions": ["bug", "test"] }, { "login": "jadengis", "name": "John Dengis", "avatar_url": "https://avatars.githubusercontent.com/u/13421336?v=4", "profile": "https://github.com/jadengis", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "dzonatan", "name": "Rokas Brazdžionis", "avatar_url": "https://avatars.githubusercontent.com/u/5166666?v=4", "profile": "https://github.com/dzonatan", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "mateusduraes", "name": "Mateus Duraes", "avatar_url": "https://avatars.githubusercontent.com/u/19319404?v=4", "profile": "https://github.com/mateusduraes", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "JJosephttg", "name": "Josh Joseph", "avatar_url": "https://avatars.githubusercontent.com/u/23690250?v=4", "profile": "https://github.com/JJosephttg", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "shaman-apprentice", "name": "Torsten Knauf", "avatar_url": "https://avatars.githubusercontent.com/u/3596742?v=4", "profile": "https://github.com/shaman-apprentice", - "contributions": [ - "maintenance" - ] + "contributions": ["maintenance"] }, { "login": "antischematic", "name": "antischematic", "avatar_url": "https://avatars.githubusercontent.com/u/12976684?v=4", "profile": "https://github.com/antischematic", - "contributions": [ - "bug", - "ideas" - ] + "contributions": ["bug", "ideas"] }, { "login": "TrustNoOneElse", "name": "Florian Pabst", "avatar_url": "https://avatars.githubusercontent.com/u/25935352?v=4", "profile": "https://github.com/TrustNoOneElse", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "markgoho", "name": "Mark Goho", "avatar_url": "https://avatars.githubusercontent.com/u/9759954?v=4", "profile": "https://rochesterparks.org", - "contributions": [ - "maintenance", - "doc" - ] + "contributions": ["maintenance", "doc"] }, { "login": "jwbaart", "name": "Jan-Willem Baart", "avatar_url": "https://avatars.githubusercontent.com/u/10973990?v=4", "profile": "http://jwbaart.dev", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "mumenthalers", "name": "S. Mumenthaler", "avatar_url": "https://avatars.githubusercontent.com/u/3604424?v=4", "profile": "https://github.com/mumenthalers", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "andreialecu", "name": "Andrei Alecu", "avatar_url": "https://avatars.githubusercontent.com/u/697707?v=4", "profile": "https://lets.poker/", - "contributions": [ - "code", - "ideas", - "doc" - ] + "contributions": ["code", "ideas", "doc"] }, { "login": "Hyperxq", "name": "Daniel Ramírez Barrientos", "avatar_url": "https://avatars.githubusercontent.com/u/22332354?v=4", "profile": "https://github.com/Hyperxq", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "mlz11", "name": "Mahdi Lazraq", "avatar_url": "https://avatars.githubusercontent.com/u/94069699?v=4", "profile": "https://github.com/mlz11", - "contributions": [ - "code", - "test" - ] + "contributions": ["code", "test"] }, { "login": "Arthie", "name": "Arthur Petrie", "avatar_url": "https://avatars.githubusercontent.com/u/16376476?v=4", "profile": "https://arthurpetrie.com", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "FabienDehopre", "name": "Fabien Dehopré", "avatar_url": "https://avatars.githubusercontent.com/u/97023?v=4", "profile": "https://github.com/FabienDehopre", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "jvereecken", "name": "Jamie Vereecken", "avatar_url": "https://avatars.githubusercontent.com/u/108937550?v=4", "profile": "https://github.com/jvereecken", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "Christian24", "name": "Christian24", "avatar_url": "https://avatars.githubusercontent.com/u/2406635?v=4", "profile": "https://github.com/Christian24", - "contributions": [ - "code", - "review" - ] + "contributions": ["code", "review"] }, { "login": "mikeshtro", "name": "Michal Štrajt", "avatar_url": "https://avatars.githubusercontent.com/u/93714867?v=4", "profile": "https://github.com/mikeshtro", - "contributions": [ - "code", - "bug" - ] + "contributions": ["code", "bug"] }, { "login": "jdegand", "name": "J. Degand", "avatar_url": "https://avatars.githubusercontent.com/u/70610011?v=4", "profile": "https://github.com/jdegand", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "artaommahe", "name": "Maksim Popov", "avatar_url": "https://avatars.githubusercontent.com/u/1944061?v=4", "profile": "https://github.com/artaommahe", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "MattijsE", "name": "MattijsE", "avatar_url": "https://avatars.githubusercontent.com/u/9746064?v=4", "profile": "https://github.com/MattijsE", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "jonaskuske", "name": "Jonas Kuske", "avatar_url": "https://avatars.githubusercontent.com/u/30421456?v=4", "profile": "https://jonaskuske.com", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "rpd10", "name": "Ryan Diehl", "avatar_url": "https://avatars.githubusercontent.com/u/27014655?v=4", "profile": "https://github.com/rpd10", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "JeevanMahesha", "name": "Jeevan Mahesha", "avatar_url": "https://avatars.githubusercontent.com/u/34814862?v=4", "profile": "https://jeevanmahesha.github.io", - "contributions": [ - "doc" - ] + "contributions": ["doc"] } ], "contributorsPerLine": 7, diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ac9d248f..58088ab3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ // For format details, see https://aka.ms/devcontainer.json. { "name": "angular-testing-library", - "image": "mcr.microsoft.com/devcontainers/typescript-node:22-bullseye", + "image": "mcr.microsoft.com/devcontainers/typescript-node:24-bookworm", // Features to add to the dev container. More info: https://containers.dev/features. "features": { diff --git a/.gitignore b/.gitignore index 2da4091c..c0a82c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,4 @@ yarn.lock # System Files .DS_Store Thumbs.db -.cursor/rules/nx-rules.mdc -.github/instructions/nx.instructions.md .history diff --git a/.nxignore b/.nxignore deleted file mode 100644 index aeb6b7f1..00000000 --- a/.nxignore +++ /dev/null @@ -1 +0,0 @@ -/projects/vscode-atl-render diff --git a/README.md b/README.md index c52525ee..fb09f5ed 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ practices.
- [Table of Contents](#table-of-contents) - [The problem](#the-problem) - [This solution](#this-solution) +- [Zoneless support](#zoneless-support) - [Example](#example) - [Installation](#installation) - [Version compatibility](#version-compatibility) @@ -92,6 +93,20 @@ primary guiding principle is: > [The more your tests resemble the way your software is used, the more > confidence they can give you.][guiding-principle] +## Zoneless support + +For zoneless applications, Angular Testing Library provides a dedicated slim entry point: + +```ts +import { render } from '@testing-library/angular/zoneless'; +``` + +A schematic is available to migrate existing tests: + +```bash +ng generate @testing-library/angular:migrate-to-zoneless +``` + ## Example counter.component.ts diff --git a/angular.json b/angular.json index 5164f45c..e5146497 100644 --- a/angular.json +++ b/angular.json @@ -61,53 +61,17 @@ "sourceRoot": "apps/example-app/src", "prefix": "app", "architect": { - "build": { + "test-build": { "builder": "@angular/build:application", "options": { - "outputPath": { - "base": "dist/apps/example-app" - }, - "index": "apps/example-app/src/index.html", - "tsConfig": "apps/example-app/tsconfig.app.json", - "assets": ["apps/example-app/src/favicon.ico", "apps/example-app/src/assets"], - "styles": [], - "scripts": [], - "browser": "apps/example-app/src/main.ts" - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "anyComponentStyle", - "maximumWarning": "6kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular/build:dev-server", - "configurations": { - "production": { - "buildTarget": "example-app:build:production" - }, - "development": { - "buildTarget": "example-app:build:development" - } - }, - "defaultConfiguration": "development" + "polyfills": [], + "tsConfig": "apps/example-app/tsconfig.spec.json" + } }, "test": { "builder": "@angular/build:unit-test", "options": { + "buildTarget": "example-app:test-build", "setupFiles": ["apps/example-app/test-setup.ts"] } }, @@ -125,50 +89,6 @@ "sourceRoot": "apps/example-app-jest/src", "prefix": "app", "architect": { - "build": { - "builder": "@angular/build:application", - "options": { - "outputPath": { - "base": "dist/apps/example-app-jest" - }, - "index": "apps/example-app-jest/src/index.html", - "tsConfig": "apps/example-app-jest/tsconfig.app.json", - "assets": ["apps/example-app-jest/src/favicon.ico", "apps/example-app-jest/src/assets"], - "styles": [], - "scripts": [], - "browser": "apps/example-app-jest/src/main.ts" - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "anyComponentStyle", - "maximumWarning": "6kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular/build:dev-server", - "configurations": { - "production": { - "buildTarget": "example-app-jest:build:production" - }, - "development": { - "buildTarget": "example-app-jest:build:development" - } - }, - "defaultConfiguration": "development" - }, "test": { "builder": "@angular-builders/jest:run", "options": { @@ -189,50 +109,6 @@ "sourceRoot": "apps/example-app-karma/src", "prefix": "app", "architect": { - "build": { - "builder": "@angular/build:application", - "options": { - "outputPath": { - "base": "dist/apps/example-app-karma" - }, - "index": "apps/example-app-karma/src/index.html", - "tsConfig": "apps/example-app-karma/tsconfig.app.json", - "assets": ["apps/example-app-karma/src/favicon.ico", "apps/example-app-karma/src/assets"], - "styles": [], - "scripts": [], - "browser": "apps/example-app-karma/src/main.ts" - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "anyComponentStyle", - "maximumWarning": "6kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular/build:dev-server", - "configurations": { - "production": { - "buildTarget": "example-app-karma:build:production" - }, - "development": { - "buildTarget": "example-app-karma:build:development" - } - }, - "defaultConfiguration": "development" - }, "test": { "builder": "@angular/build:karma", "options": { diff --git a/apps/example-app-jest/eslint.config.cjs b/apps/example-app-jest/eslint.config.cjs deleted file mode 100644 index 9e951e7a..00000000 --- a/apps/example-app-jest/eslint.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check - -// TODO - https://github.com/nrwl/nx/issues/22576 - -/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigPromise} */ -const config = (async () => (await import('./eslint.config.mjs')).default)(); -module.exports = config; diff --git a/apps/example-app-jest/src/app/examples/21-deferable-view.component.ts b/apps/example-app-jest/src/app/examples/21-deferable-view.component.ts index 7b66d85a..94321593 100644 --- a/apps/example-app-jest/src/app/examples/21-deferable-view.component.ts +++ b/apps/example-app-jest/src/app/examples/21-deferable-view.component.ts @@ -10,13 +10,13 @@ export class DeferableViewChildComponent {} @Component({ template: ` @defer (on timer(2s)) { -Hello from placeholder
+Hello from placeholder
} @loading { -Hello from loading
+Hello from loading
} @error { -Hello from error
+Hello from error
} `, imports: [DeferableViewChildComponent], diff --git a/apps/example-app-jest/tsconfig.app.json b/apps/example-app-jest/tsconfig.app.json deleted file mode 100644 index 15d8d0b9..00000000 --- a/apps/example-app-jest/tsconfig.app.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [], - "allowJs": true, - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"], - "exclude": ["**/*.test.ts", "**/*.spec.ts", "jest.config.ts"], - "angularCompilerOptions": { - "extendedDiagnostics": { - "checks": { - "nullishCoalescingNotNullable": "suppress", - "optionalChainNotNullable": "suppress" - } - } - } -} diff --git a/apps/example-app-jest/tsconfig.json b/apps/example-app-jest/tsconfig.json index 01919bcd..427b633e 100644 --- a/apps/example-app-jest/tsconfig.json +++ b/apps/example-app-jest/tsconfig.json @@ -15,9 +15,6 @@ "strictTemplates": true }, "references": [ - { - "path": "./tsconfig.app.json" - }, { "path": "./tsconfig.spec.json" } diff --git a/apps/example-app-karma/eslint.config.cjs b/apps/example-app-karma/eslint.config.cjs deleted file mode 100644 index 9e951e7a..00000000 --- a/apps/example-app-karma/eslint.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check - -// TODO - https://github.com/nrwl/nx/issues/22576 - -/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigPromise} */ -const config = (async () => (await import('./eslint.config.mjs')).default)(); -module.exports = config; diff --git a/apps/example-app-karma/karma.conf.js b/apps/example-app-karma/karma.conf.js index 185b0883..96fe548a 100644 --- a/apps/example-app-karma/karma.conf.js +++ b/apps/example-app-karma/karma.conf.js @@ -4,7 +4,7 @@ module.exports = function (config) { try { config.set({ basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], + frameworks: ['jasmine'], plugins: [require('karma-jasmine'), require('karma-chrome-launcher')], client: { jasmine: { diff --git a/apps/example-app-karma/src/app/examples/login-form.spec.ts b/apps/example-app-karma/src/app/examples/login-form.spec.ts index 20d7e12a..d13bee46 100644 --- a/apps/example-app-karma/src/app/examples/login-form.spec.ts +++ b/apps/example-app-karma/src/app/examples/login-form.spec.ts @@ -37,11 +37,11 @@ it('should display invalid message and submit button must be disabled', async () diff --git a/apps/example-app-karma/tsconfig.app.json b/apps/example-app-karma/tsconfig.app.json deleted file mode 100644 index b00da0d5..00000000 --- a/apps/example-app-karma/tsconfig.app.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [], - "allowJs": true, - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"], - "exclude": ["**/*.test.ts", "**/*.spec.ts"], - "angularCompilerOptions": { - "extendedDiagnostics": { - "checks": { - "nullishCoalescingNotNullable": "suppress", - "optionalChainNotNullable": "suppress" - } - } - } -} diff --git a/apps/example-app-karma/tsconfig.json b/apps/example-app-karma/tsconfig.json index 3b84e46e..233d6c60 100644 --- a/apps/example-app-karma/tsconfig.json +++ b/apps/example-app-karma/tsconfig.json @@ -14,9 +14,6 @@ "strictTemplates": true }, "references": [ - { - "path": "./tsconfig.app.json" - }, { "path": "./tsconfig.spec.json" } diff --git a/apps/example-app/eslint.config.cjs b/apps/example-app/eslint.config.cjs deleted file mode 100644 index 9e951e7a..00000000 --- a/apps/example-app/eslint.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check - -// TODO - https://github.com/nrwl/nx/issues/22576 - -/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigPromise} */ -const config = (async () => (await import('./eslint.config.mjs')).default)(); -module.exports = config; 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 index 7b66d85a..94321593 100644 --- a/apps/example-app/src/app/examples/21-deferable-view.component.ts +++ b/apps/example-app/src/app/examples/21-deferable-view.component.ts @@ -10,13 +10,13 @@ export class DeferableViewChildComponent {} @Component({ template: ` @defer (on timer(2s)) { -Hello from placeholder
+Hello from placeholder
} @loading { -Hello from loading
+Hello from loading
} @error { -Hello from error
+Hello from error
} `, imports: [DeferableViewChildComponent], diff --git a/apps/example-app/tsconfig.app.json b/apps/example-app/tsconfig.app.json deleted file mode 100644 index b00da0d5..00000000 --- a/apps/example-app/tsconfig.app.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [], - "allowJs": true, - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"], - "exclude": ["**/*.test.ts", "**/*.spec.ts"], - "angularCompilerOptions": { - "extendedDiagnostics": { - "checks": { - "nullishCoalescingNotNullable": "suppress", - "optionalChainNotNullable": "suppress" - } - } - } -} diff --git a/apps/example-app/tsconfig.json b/apps/example-app/tsconfig.json index 160ba1ed..d02e2387 100644 --- a/apps/example-app/tsconfig.json +++ b/apps/example-app/tsconfig.json @@ -15,9 +15,6 @@ "strictTemplates": true }, "references": [ - { - "path": "./tsconfig.app.json" - }, { "path": "./tsconfig.spec.json" } diff --git a/eslint.config.cjs b/eslint.config.cjs deleted file mode 100644 index 9e951e7a..00000000 --- a/eslint.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check - -// TODO - https://github.com/nrwl/nx/issues/22576 - -/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigPromise} */ -const config = (async () => (await import('./eslint.config.mjs')).default)(); -module.exports = config; diff --git a/eslint.config.mjs b/eslint.config.mjs index 421c2e45..1f9c4dc8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -42,8 +42,8 @@ export default tseslint.config( caughtErrorsIgnorePattern: '^_', }, ], - "@angular-eslint/prefer-standalone": "off", - "@angular-eslint/no-input-rename": "off", + '@angular-eslint/prefer-standalone': 'off', + '@angular-eslint/no-input-rename': 'off', }, }, { @@ -54,7 +54,7 @@ export default tseslint.config( files: ['**/*.html'], extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], rules: { - "@angular-eslint/template/prefer-control-flow": "off", + '@angular-eslint/template/prefer-control-flow': 'off', }, }, ); diff --git a/package.json b/package.json index 8c248767..0a0218a6 100644 --- a/package.json +++ b/package.json @@ -20,69 +20,69 @@ "prepare": "git config core.hookspath .githooks" }, "dependencies": { - "@angular/cdk": "22.0.0", - "@angular/common": "22.0.2", - "@angular/compiler": "22.0.2", - "@angular/core": "22.0.2", - "@angular/material": "22.0.0", - "@angular/platform-browser": "22.0.2", - "@angular/router": "22.0.2", - "@ngrx/store": "21.1.0", + "@angular/cdk": "22.1.2", + "@angular/common": "22.1.1", + "@angular/compiler": "22.1.1", + "@angular/core": "22.1.1", + "@angular/material": "22.1.2", + "@angular/platform-browser": "22.1.1", + "@angular/router": "22.1.1", + "@ngrx/store": "21.1.1", "@testing-library/dom": "^10.4.1", - "rxjs": "7.8.0", + "rxjs": "7.8.2", "tslib": "~2.8.1", - "zone.js": "^0.15.1" + "zone.js": "^0.16.2" }, "devDependencies": { "@angular-builders/jest": "^22.0.1", - "@angular-devkit/core": "22.0.0", - "@angular-devkit/schematics": "22.0.0", - "@angular-eslint/builder": "22.0.0", - "@angular-eslint/eslint-plugin": "22.0.0", - "@angular-eslint/eslint-plugin-template": "22.0.0", - "@angular-eslint/schematics": "22.0.0", - "@angular-eslint/template-parser": "22.0.0", - "@angular/build": "^22.0.0", - "@angular/cli": "~22.0.0", - "@angular/compiler-cli": "22.0.2", - "@angular/forms": "22.0.2", - "@angular/language-service": "22.0.2", + "@angular-devkit/core": "22.1.4", + "@angular-devkit/schematics": "22.1.4", + "@angular-eslint/builder": "22.1.0", + "@angular-eslint/eslint-plugin": "22.1.0", + "@angular-eslint/eslint-plugin-template": "22.1.0", + "@angular-eslint/schematics": "22.1.0", + "@angular-eslint/template-parser": "22.1.0", + "@angular/build": "^22.1.4", + "@angular/cli": "~22.1.4", + "@angular/compiler-cli": "22.1.1", + "@angular/forms": "22.1.1", + "@angular/language-service": "22.1.1", "@eslint/eslintrc": "^3.3.1", - "@schematics/angular": "22.0.0", + "@schematics/angular": "22.1.4", "@testing-library/jasmine-dom": "^1.3.3", "@testing-library/jest-dom": "^6.9.1", - "@testing-library/user-event": "^14.6.1", + "@testing-library/user-event": "^14.6.4", "@types/jasmine": "4.3.1", "@types/jest": "30.0.0", - "@types/node": "22.10.1", + "@types/node": "24.13.3", "@types/testing-library__jasmine-dom": "^1.3.4", - "@typescript-eslint/types": "^8.46.3", - "@typescript-eslint/utils": "^8.46.3", - "angular-eslint": "22.0.0", + "@typescript-eslint/types": "^8.67.0", + "@typescript-eslint/utils": "^8.67.0", + "angular-eslint": "22.1.0", "autoprefixer": "^10.4.21", "cpy-cli": "^6.0.0", "eslint": "^9.39.1", - "eslint-plugin-jest-dom": "~5.5.0", - "eslint-plugin-testing-library": "~7.13.3", + "eslint-plugin-jest-dom": "~5.10.1", + "eslint-plugin-testing-library": "~7.16.2", "istanbul-lib-instrument": "^6.0.3", "jasmine-core": "4.2.0", "jasmine-spec-reporter": "7.0.0", - "jest": "30.2.0", - "jest-environment-jsdom": "30.2.0", + "jest": "30.4.2", + "jest-environment-jsdom": "30.4.1", "jest-preset-angular": "^17.0.0", "jsdom": "^27.3.0", - "karma": "6.4.0", + "karma": "6.4.4", "karma-chrome-launcher": "^3.2.0", "karma-coverage": "^2.2.1", "karma-jasmine": "5.1.0", - "karma-jasmine-html-reporter": "2.0.0", + "karma-jasmine-html-reporter": "2.2.0", "lint-staged": "^16.2.6", - "ng-mocks": "^14.14.0", - "ng-packagr": "22.0.0", - "prettier": "2.6.2", + "ng-mocks": "^14.17.1", + "ng-packagr": "22.1.1", + "prettier": "3.9.6", "rimraf": "^6.1.0", "typescript": "6.0.3", - "typescript-eslint": "^8.46.3", - "vitest": "4.0.15" + "typescript-eslint": "^8.67.0", + "vitest": "4.1.10" } } diff --git a/projects/testing-library/eslint.config.cjs b/projects/testing-library/eslint.config.cjs deleted file mode 100644 index 9e951e7a..00000000 --- a/projects/testing-library/eslint.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check - -// TODO - https://github.com/nrwl/nx/issues/22576 - -/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigPromise} */ -const config = (async () => (await import('./eslint.config.mjs')).default)(); -module.exports = config; diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json index 9310b7a5..44ebb5a4 100644 --- a/projects/testing-library/package.json +++ b/projects/testing-library/package.json @@ -29,8 +29,6 @@ "migrations": "./schematics/migrations/migrations.json" }, "peerDependencies": { - "@angular/common": ">= 21.0.0", - "@angular/platform-browser": ">= 21.0.0", "@angular/router": ">= 21.0.0", "@angular/core": ">= 21.0.0", "@testing-library/dom": "^10.0.0" diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts index f4452833..19f9d36a 100644 --- a/projects/testing-library/src/lib/models.ts +++ b/projects/testing-library/src/lib/models.ts @@ -25,8 +25,8 @@ export type OutputRefKeysWithCallback= BoundFunctions; @@ -113,8 +113,8 @@ export type ComponentInput= [P in keyof T]?: T[P] extends InputSignalWithTransform ? U : T[P] extends Signal - ? U - : T[P]; + ? U + : T[P]; } | AliasedInputs; @@ -529,9 +529,12 @@ export interface ComponentOverride { providers: Provider[]; } -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface RenderTemplateOptions - extends RenderComponentOptions { +export interface RenderTemplateOptions< + WrapperType, + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + Properties extends object = {}, + Q extends Queries = typeof queries, +> extends RenderComponentOptions { /** * @description * An Angular component to wrap the component in. diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index e9b52160..f986beb3 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -143,18 +143,21 @@ export async function render { - const [key, value] = q.split('='); - const currentValue = qp[key]; - if (typeof currentValue === 'undefined') { - qp[key] = value; - } else if (Array.isArray(currentValue)) { - qp[key] = [...currentValue, value]; - } else { - qp[key] = [currentValue, value]; - } - return qp; - }, {} as Record ) + ? params.split('&').reduce( + (qp, q) => { + const [key, value] = q.split('='); + const currentValue = qp[key]; + if (typeof currentValue === 'undefined') { + qp[key] = value; + } else if (Array.isArray(currentValue)) { + qp[key] = [...currentValue, value]; + } else { + qp[key] = [currentValue, value]; + } + return qp; + }, + {} as Record , + ) : undefined; const navigateOptions: NavigationExtras | undefined = queryParams @@ -247,7 +250,7 @@ export async function render 0) { - const changes = getChangesObj(null, componentProperties); + const changes = getChangesObj(null, properties); createdFixture.componentInstance.ngOnChanges(changes); } @@ -505,10 +508,13 @@ function hasOnChangesHook (componentInstance: SutType): componentInstanc function getChangesObj(oldProps: Record | null, newProps: Record ) { const isFirstChange = oldProps === null; - return Object.keys(newProps).reduce ((changes, key) => { - changes[key] = new SimpleChange(isFirstChange ? null : oldProps[key], newProps[key], isFirstChange); - return changes; - }, {} as Record ); + return Object.keys(newProps).reduce ( + (changes, key) => { + changes[key] = new SimpleChange(isFirstChange ? null : oldProps[key], newProps[key], isFirstChange); + return changes; + }, + {} as Record , + ); } function update ( @@ -690,20 +696,23 @@ class WrapperComponent {} * Wrap findBy queries to poke the Angular change detection cycle */ function replaceFindWithFindAndDetectChanges >(originalQueriesForContainer: T): T { - return Object.keys(originalQueriesForContainer).reduce((newQueries, key) => { - const getByQuery = originalQueriesForContainer[key.replace('find', 'get')]; - if (key.startsWith('find') && getByQuery) { - newQueries[key] = async (...queryOptions: any[]) => { - const waitOptions = queryOptions.length === 3 ? queryOptions.pop() : undefined; - // original implementation at https://github.com/testing-library/dom-testing-library/blob/main/src/query-helpers.js - return await waitForWrapper(detectChangesForMountedFixtures, () => getByQuery(...queryOptions), waitOptions); - }; - } else { - newQueries[key] = originalQueriesForContainer[key]; - } + return Object.keys(originalQueriesForContainer).reduce( + (newQueries, key) => { + const getByQuery = originalQueriesForContainer[key.replace('find', 'get')]; + if (key.startsWith('find') && getByQuery) { + newQueries[key] = async (...queryOptions: any[]) => { + const waitOptions = queryOptions.length === 3 ? queryOptions.pop() : undefined; + // original implementation at https://github.com/testing-library/dom-testing-library/blob/main/src/query-helpers.js + return await waitForWrapper(detectChangesForMountedFixtures, () => getByQuery(...queryOptions), waitOptions); + }; + } else { + newQueries[key] = originalQueriesForContainer[key]; + } - return newQueries; - }, {} as Record ) as T; + return newQueries; + }, + {} as Record , + ) as T; } /** @@ -723,7 +732,8 @@ function safeDetectChanges (fixture: ComponentFixture ) { fixture.detectChanges(); } } catch (err: any) { - if (!err.message.startsWith('ViewDestroyedError') && !err.message.startsWith('NG0205')) { + const message = typeof err?.message === 'string' ? err.message : ''; + if (!message.startsWith('ViewDestroyedError') && !message.startsWith('NG0205')) { throw err; } } diff --git a/projects/testing-library/src/tests/defer-blocks.spec.ts b/projects/testing-library/src/tests/defer-blocks.spec.ts index d4325346..6a6a2a67 100644 --- a/projects/testing-library/src/tests/defer-blocks.spec.ts +++ b/projects/testing-library/src/tests/defer-blocks.spec.ts @@ -78,9 +78,9 @@ test('renders a defer block in an initial state using the array syntax', async ( @Component({ template: ` @defer { - Defer block content
+Defer block content
} @loading { -Loading...
+Loading...
} `, }) @@ -89,8 +89,8 @@ class FixtureComponent {} @Component({ template: ` - @defer(on interaction(trigger)) { -empty defer block+ @defer (on interaction(trigger)) { +empty defer block} `, }) diff --git a/projects/testing-library/src/tests/vitest-utils/create-mock.spec.ts b/projects/testing-library/src/tests/vitest-utils/create-mock.spec.ts index 15d11631..e9313983 100644 --- a/projects/testing-library/src/tests/vitest-utils/create-mock.spec.ts +++ b/projects/testing-library/src/tests/vitest-utils/create-mock.spec.ts @@ -5,7 +5,10 @@ import { fireEvent, render, screen } from '../../public_api'; import { createMock, provideMock, provideMockWithValues } from '../../../vitest-utils'; class FixtureService { - constructor(private foo: string, public bar: string) {} + constructor( + private foo: string, + public bar: string, + ) {} print() { console.log(this.foo, this.bar); diff --git a/projects/testing-library/src/tests/wait-for-element-to-be-removed.spec.ts b/projects/testing-library/src/tests/wait-for-element-to-be-removed.spec.ts index ed5bd8fb..d4e72ae4 100644 --- a/projects/testing-library/src/tests/wait-for-element-to-be-removed.spec.ts +++ b/projects/testing-library/src/tests/wait-for-element-to-be-removed.spec.ts @@ -7,7 +7,7 @@ import { test, expect } from 'vitest'; selector: 'atl-fixture', template: ` @if (visible()) { -👋+👋} `, }) diff --git a/projects/testing-library/zoneless/src/public_api.ts b/projects/testing-library/zoneless/src/public_api.ts index ef200859..64736f60 100644 --- a/projects/testing-library/zoneless/src/public_api.ts +++ b/projects/testing-library/zoneless/src/public_api.ts @@ -90,28 +90,28 @@ export interface RenderOptions{ /** * @description - * Determines whether `fixture.detectChanges()` is called after the component is rendered. + * Determines whether the initial `fixture.detectChanges()` after the component is rendered is skipped. * * @default - * true + * false * * @example * await render(AppComponent, { - * skipDetectChanges: false + * skipDetectChanges: true * }) */ skipDetectChanges?: boolean; /** * @description - * Determines whether `fixture.whenStable()` is called after the component is rendered. + * Determines whether `fixture.whenStable()` is awaited after the component is rendered. * * @default - * true + * false * * @example * await render(AppComponent, { - * waitForStableOnRender: false + * waitForStableOnRender: true * }) */ waitForStableOnRender?: boolean; @@ -170,9 +170,12 @@ export interface RenderComponentOptionsexte importOverrides?: ImportOverride[]; } -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface RenderTemplateOptions- extends RenderOptions { +export interface RenderTemplateOptions< + WrapperType, + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + Properties extends object = {}, + Q extends Queries = typeof queries, +> extends RenderOptions{ /** * @description * An Angular component to wrap the component in.