From 53b5400724bc9d4dec564557c7803259185a54d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Herman?= Date: Tue, 3 Mar 2026 00:45:06 +0100 Subject: [PATCH] feat: support Vitest as configured by Angular 21 This commit adds support for Vitest in ngMocks.autoSpy and updates the testing infrastructure to support running tests under Vitest, by factoring common mock creation methods. Configuration-wise, AOT compilation does not work and has to be disabled, which is how it works with the previous Karma builder. This is due to NGCC not interpreting non-litterals in component decorators, meaning all components became non-standalone which broke all module-based tests. Angular dropped support for fakeAsync utilities handled by Zone.js when using the Vitest runner, meaning these tests have to be migrated to async-await, which has been done in a way that still allows to verify the legacy behavior under test runners which support it. --- README.md | 40 +- e2e/a21/angular.json | 18 + e2e/a21/package-lock.json | 438 +++- e2e/a21/package.json | 10 +- e2e/a21/src/setup-vitest.ts | 21 + e2e/a21/tsconfig.json | 6 +- e2e/a21/vitest.config.ts | 8 + e2e/a22/angular.json | 18 + e2e/a22/package-lock.json | 391 +++- e2e/a22/package.json | 10 +- e2e/a22/src/setup-vitest.ts | 21 + e2e/a22/tsconfig.json | 6 +- e2e/a22/vitest.config.ts | 8 + examples/MockActivatedRoute/test.spec.ts | 34 +- examples/MockComponent/test.spec.ts | 8 +- examples/MockDirective-Attribute/test.spec.ts | 8 +- examples/MockForms/test.spec.ts | 12 +- examples/MockPipe/test.spec.ts | 10 +- examples/MockReactiveForms/test.spec.ts | 12 +- examples/MockRender/test.spec.ts | 22 +- examples/TestStandalonePipe/test.spec.ts | 6 +- examples/main/test.spec.ts | 10 +- examples/ngMocksFaster/test.spec.ts | 28 +- examples/readme/builder.spec.ts | 6 +- examples/readme/classic.spec.ts | 6 +- libs/ng-mocks/package.json | 2 +- .../lib/mock-helper/mock-helper.auto-spy.ts | 8 +- .../src/lib/mock-helper/mock-helper.ts | 2 +- package-lock.json | 1821 +++++++++++++---- package.json | 7 +- .../test.spec.ts | 74 +- .../test.spec.ts | 74 +- tests/fake-async/test.spec.ts | 12 + tests/func.get-vitest.ts | 8 + tests/func.has-vitest.ts | 5 + tests/get-inputs-and-outputs/test.spec.ts | 17 +- tests/issue-10960/test.spec.ts | 7 +- tests/issue-162/test.spec.ts | 81 +- tests/issue-166/test.spec.ts | 5 +- tests/issue-167/component.spec.ts | 30 +- tests/issue-167/directive.spec.ts | 30 +- tests/issue-167/ng-validators.spec.ts | 10 +- tests/issue-240/test.classic.spec.ts | 14 +- tests/issue-240/test.real.spec.ts | 14 +- tests/issue-246/test.spec.ts | 31 +- tests/issue-2647/ignore.spec.ts | 5 +- tests/issue-2647/warn.spec.ts | 5 +- tests/issue-305/overrides.spec.ts | 14 +- tests/issue-3265/test.spec.ts | 8 +- tests/issue-434/test.spec.ts | 20 +- tests/issue-455/abstract.spec.ts | 39 +- tests/issue-455/token.spec.ts | 29 +- tests/issue-488/test.spec.ts | 14 +- tests/issue-572/test.spec.ts | 5 +- tests/issue-621/test.spec.ts | 16 +- tests/issue-625/test.spec.ts | 8 +- tests/issue-735/test.spec.ts | 27 +- tests/issue-736/test.spec.ts | 15 +- tests/mock-helper-flush-test-bed/test.spec.ts | 32 +- tests/mock-helpers.ts | 62 + tests/mock-render-param-ref/test.spec.ts | 14 +- tests/ng-mocks-change/cdr-change.spec.ts | 10 +- tests/ng-mocks-change/cdr-input.spec.ts | 10 +- tests/ng-mocks-click/317.spec.ts | 8 +- tests/ng-mocks-crawl/test.spec.ts | 8 +- tests/ng-mocks-output/317.spec.ts | 5 +- tests/ng-mocks-stub-member/test.spec.ts | 32 +- tests/ng-mocks-trigger/317.spec.ts | 5 +- tests/performance/test.spec.ts | 10 +- tests/spies/test.spec.ts | 27 +- tsconfig.json | 3 +- 71 files changed, 2861 insertions(+), 979 deletions(-) create mode 100644 e2e/a21/src/setup-vitest.ts create mode 100644 e2e/a21/vitest.config.ts create mode 100644 e2e/a22/src/setup-vitest.ts create mode 100644 e2e/a22/vitest.config.ts create mode 100644 tests/func.get-vitest.ts create mode 100644 tests/func.has-vitest.ts create mode 100644 tests/mock-helpers.ts diff --git a/README.md b/README.md index 1af0044a8c..cfdba776e7 100644 --- a/README.md +++ b/README.md @@ -13,26 +13,26 @@ The current version of the library **has been tested** and **can be used** with: -| angular | ng-mocks | jasmine | jest | ivy | standalone | signals | defer | -| ------: | :------: | :-----: | :--: | :-: | :--------: | :-----: | :---: | -| 22 | latest | yes | yes | yes | yes | yes | no | -| 21 | latest | yes | yes | yes | yes | yes | no | -| 20 | latest | yes | yes | yes | yes | yes | no | -| 19 | latest | yes | yes | yes | yes | yes | no | -| 18 | latest | yes | yes | yes | yes | yes | no | -| 17 | latest | yes | yes | yes | yes | yes | no | -| 16 | latest | yes | yes | yes | yes | yes | | -| 15 | latest | yes | yes | yes | yes | | | -| 14 | latest | yes | yes | yes | yes | | | -| 13 | latest | yes | yes | yes | | | | -| 12 | latest | yes | yes | yes | | | | -| 11 | latest | yes | yes | yes | | | | -| 10 | latest | yes | yes | yes | | | | -| 9 | latest | yes | yes | yes | | | | -| 8 | latest | yes | yes | | | | | -| 7 | latest | yes | yes | | | | | -| 6 | latest | yes | yes | | | | | -| 5 | latest | yes | yes | | | | | +| angular | ng-mocks | jasmine | jest | vitest | ivy | standalone | signals | defer | +| ------: | :------: | :-----: | :--: | :----: | :-: | :--------: | :-----: | :---: | +| 22 | latest | yes | yes | yes | yes | yes | yes | no | +| 21 | latest | yes | yes | yes | yes | yes | yes | no | +| 20 | latest | yes | yes | | yes | yes | yes | no | +| 19 | latest | yes | yes | | yes | yes | yes | no | +| 18 | latest | yes | yes | | yes | yes | yes | no | +| 17 | latest | yes | yes | | yes | yes | yes | no | +| 16 | latest | yes | yes | | yes | yes | yes | | +| 15 | latest | yes | yes | | yes | yes | | | +| 14 | latest | yes | yes | | yes | yes | | | +| 13 | latest | yes | yes | | yes | | | | +| 12 | latest | yes | yes | | yes | | | | +| 11 | latest | yes | yes | | yes | | | | +| 10 | latest | yes | yes | | yes | | | | +| 9 | latest | yes | yes | | yes | | | | +| 8 | latest | yes | yes | | | | | | +| 7 | latest | yes | yes | | | | | | +| 6 | latest | yes | yes | | | | | | +| 5 | latest | yes | yes | | | | | | ## Important links diff --git a/e2e/a21/angular.json b/e2e/a21/angular.json index 3657c74aea..074a6cc813 100644 --- a/e2e/a21/angular.json +++ b/e2e/a21/angular.json @@ -24,6 +24,13 @@ "optimization": false, "extractLicenses": false, "sourceMap": true + }, + "testing": { + "aot": false, + "optimization": false, + "extractLicenses": false, + "sourceMap": true, + "polyfills": ["zone.js", "zone.js/testing"] } }, "defaultConfiguration": "production" @@ -49,6 +56,17 @@ "karmaConfig": "karma.conf.js", "watch": false } + }, + "vitest": { + "builder": "@angular/build:unit-test", + "options": { + "runner": "vitest", + "tsConfig": "tsconfig.json", + "providersFile": "src/setup-vitest.ts", + "buildTarget": "a21:build:testing", + "runnerConfig": "vitest.config.ts", + "watch": false + } } } }, diff --git a/e2e/a21/package-lock.json b/e2e/a21/package-lock.json index 916ea57a59..242d66b7a8 100644 --- a/e2e/a21/package-lock.json +++ b/e2e/a21/package-lock.json @@ -31,6 +31,7 @@ "jest": "30.3.0", "jest-environment-jsdom": "30.3.0", "jest-preset-angular": "16.1.1", + "jsdom": "29.0.0", "karma": "6.4.4", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", @@ -40,7 +41,8 @@ "npm": "11.11.1", "puppeteer": "24.39.1", "ts-node": "10.9.2", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "4.1.0" }, "engines": { "npm": "11.11.1" @@ -654,7 +656,6 @@ "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-color-parser": "^4.0.2", @@ -672,7 +673,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -683,7 +683,6 @@ "integrity": "sha512-Q6mU0Z6bfj6YvnX2k9n0JxiIwrCFN59x/nWmYQnAqP000ruX/yV+5bp/GRcF5T8ncvfwJQ7fgfP74DlpKExILA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", @@ -701,7 +700,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -711,8 +709,7 @@ "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.29.0", @@ -940,23 +937,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { @@ -1269,7 +1266,6 @@ "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "css-tree": "^3.0.0" }, @@ -1327,7 +1323,6 @@ } ], "license": "MIT-0", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -1348,7 +1343,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1373,7 +1367,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@csstools/color-helpers": "^6.0.2", "@csstools/css-calc": "^3.1.1" @@ -1402,7 +1395,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1426,7 +1418,6 @@ } ], "license": "MIT-0", - "peer": true, "peerDependencies": { "css-tree": "^3.2.1" }, @@ -1452,7 +1443,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -1939,7 +1929,6 @@ "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, @@ -5136,6 +5125,17 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", @@ -5146,6 +5146,13 @@ "@types/node": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -5574,6 +5581,136 @@ "vite": "^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/expect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.0", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.0", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -5801,6 +5938,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -6088,7 +6235,6 @@ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "require-from-string": "^2.0.2" } @@ -6424,6 +6570,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7006,7 +7162,6 @@ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" @@ -7201,7 +7356,6 @@ "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" @@ -7713,6 +7867,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -7991,6 +8152,16 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/exponential-backoff": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", @@ -8696,7 +8867,6 @@ "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@exodus/bytes": "^1.6.0" }, @@ -10263,7 +10433,6 @@ "integrity": "sha512-9FshNB6OepopZ08unmmGpsF7/qCjxGPbo3NbgfJAnPeHXnsODE9WWffXZtRFRFe0ntzaAOcSKNJFz8wiyvF1jQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/css-color": "^5.0.1", "@asamuzakjp/dom-selector": "^7.0.2", @@ -10305,7 +10474,6 @@ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.12" }, @@ -10319,7 +10487,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -10330,7 +10497,6 @@ "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "entities": "^6.0.0" }, @@ -10339,12 +10505,11 @@ } }, "node_modules/jsdom/node_modules/undici": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.3.tgz", - "integrity": "sha512-eJdUmK/Wrx2d+mnWWmwwLRyA7OQCkLap60sk3dOK4ViZR7DKwwptwuIvFBg2HaiP9ESaEdhtpSymQPvytpmkCA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.4.tgz", + "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20.18.1" } @@ -11390,14 +11555,15 @@ "license": "ISC" }, "node_modules/make-fetch-happen": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.4.tgz", - "integrity": "sha512-vM2sG+wbVeVGYcCm16mM3d5fuem9oC28n436HjsGO3LcxoTI8LNVa4rwZDn3f76+cWyT4GGJDxjTYU1I2nr6zw==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", + "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", "dev": true, "license": "ISC", "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", @@ -11437,8 +11603,7 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/media-typer": { "version": "1.1.0", @@ -14186,6 +14351,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -14657,6 +14833,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -15474,9 +15657,9 @@ } }, "node_modules/sax": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", - "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "dev": true, "license": "BlueOak-1.0.0", "optional": true, @@ -15663,6 +15846,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -15987,6 +16177,13 @@ "node": ">=10" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -15997,6 +16194,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.3.1.tgz", @@ -16393,6 +16597,23 @@ "b4a": "^1.6.4" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -16410,27 +16631,35 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", - "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", + "version": "7.0.26", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.26.tgz", + "integrity": "sha512-WiGwQjr0qYdNNG8KpMKlSvpxz652lqa3Rd+/hSaDcY4Uo6SKWZq2LAF+hsAhUewTtYhXlorBKgNF3Kk8hnjGoQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "tldts-core": "^7.0.25" + "tldts-core": "^7.0.26" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", - "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==", + "version": "7.0.26", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.26.tgz", + "integrity": "sha512-5WJ2SqFsv4G2Dwi7ZFVRnz6b2H1od39QME1lc2y5Ew3eWiZMAeqOAfWpRP9jHvhUl881406QtZTODvjttJs+ew==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tmp": { "version": "0.2.5", @@ -16478,7 +16707,6 @@ "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "tldts": "^7.0.5" }, @@ -16492,7 +16720,6 @@ "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "punycode": "^2.3.1" }, @@ -16506,7 +16733,6 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -17005,6 +17231,88 @@ } } }, + "node_modules/vitest": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -17073,7 +17381,6 @@ "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=20" } @@ -17111,7 +17418,6 @@ "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" } @@ -17122,7 +17428,6 @@ "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", @@ -17148,6 +17453,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/e2e/a21/package.json b/e2e/a21/package.json index 68171bdbe3..49c3433914 100644 --- a/e2e/a21/package.json +++ b/e2e/a21/package.json @@ -7,12 +7,14 @@ "ng": "ng", "start": "ng serve", "build": "ng build", - "test": "npm run test:jasmine && npm run test:jest", + "test": "npm run test:jasmine && npm run test:jest && npm run test:vitest", "test:debug": "npm run test:jasmine:debug", "test:jasmine": "ng test --ts-config ./tsconfig.json --progress=false --no-watch", "test:jasmine:debug": "npm run test:jasmine -- --watch --browsers Chrome", "test:jest": "jest --config jest.config.ts", - "test:jest:debug": "jest -i --watch" + "test:jest:debug": "jest -i --watch", + "test:vitest": "ng run a21:vitest --progress=false --no-watch", + "test:vitest:debug": "npm run test:vitest -- --watch" }, "private": true, "dependencies": { @@ -39,6 +41,7 @@ "jest": "30.3.0", "jest-environment-jsdom": "30.3.0", "jest-preset-angular": "16.1.1", + "jsdom": "29.0.0", "karma": "6.4.4", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", @@ -48,7 +51,8 @@ "npm": "11.11.1", "puppeteer": "24.39.1", "ts-node": "10.9.2", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "4.1.0" }, "engines": { "npm": "11.11.1" diff --git a/e2e/a21/src/setup-vitest.ts b/e2e/a21/src/setup-vitest.ts new file mode 100644 index 0000000000..36fe6b7ab3 --- /dev/null +++ b/e2e/a21/src/setup-vitest.ts @@ -0,0 +1,21 @@ +import { MockService, ngMocks } from 'ng-mocks'; // eslint-disable-line import-x/order + +ngMocks.autoSpy('vitest'); + +// In case, if you use @angular/router and Angular 14+. +// You might want to set a mock of DefaultTitleStrategy as TitleStrategy. +// A14 fix: making DefaultTitleStrategy to be a default mock for TitleStrategy +import { DefaultTitleStrategy, TitleStrategy } from '@angular/router'; // eslint-disable-line import-x/order +ngMocks.defaultMock(TitleStrategy, () => MockService(DefaultTitleStrategy)); + +// Usually, *ngIf and other declarations from CommonModule aren't expected to be mocked. +// The code below keeps them. +import { CommonModule } from '@angular/common'; // eslint-disable-line import-x/order +import { ApplicationModule, provideZoneChangeDetection } from '@angular/core'; // eslint-disable-line import-x/order +import { BrowserModule } from '@angular/platform-browser'; // eslint-disable-line import-x/order +ngMocks.globalKeep(ApplicationModule, true); +ngMocks.globalKeep(CommonModule, true); +ngMocks.globalKeep(BrowserModule, true); + +// Return providers that Angular should setup in the testing environment. +export default [provideZoneChangeDetection()]; diff --git a/e2e/a21/tsconfig.json b/e2e/a21/tsconfig.json index df6801f12d..29988b3ac6 100644 --- a/e2e/a21/tsconfig.json +++ b/e2e/a21/tsconfig.json @@ -16,7 +16,7 @@ "target": "ES2022", "module": "preserve", "useDefineForClassFields": false, - "types": ["jasmine", "jest", "node"] + "types": ["jasmine", "jest", "vitest/globals", "node"] }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, @@ -24,6 +24,6 @@ "strictInputAccessModifiers": true, "strictTemplates": true }, - "files": ["src/main.ts", "src/test.ts", "src/setup-jest.ts"], - "include": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] + "files": ["src/main.ts", "src/test.ts", "src/setup-jest.ts", "src/setup-vitest.ts"], + "include": ["jest.config.ts", "vitest.config.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] } diff --git a/e2e/a21/vitest.config.ts b/e2e/a21/vitest.config.ts new file mode 100644 index 0000000000..c4a85d8112 --- /dev/null +++ b/e2e/a21/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + maxConcurrency: 1, + fileParallelism: false, + }, +}); diff --git a/e2e/a22/angular.json b/e2e/a22/angular.json index 166ebfea48..995ea9e806 100644 --- a/e2e/a22/angular.json +++ b/e2e/a22/angular.json @@ -24,6 +24,13 @@ "optimization": false, "extractLicenses": false, "sourceMap": true + }, + "testing": { + "aot": false, + "optimization": false, + "extractLicenses": false, + "sourceMap": true, + "polyfills": ["zone.js", "zone.js/testing"] } }, "defaultConfiguration": "production" @@ -49,6 +56,17 @@ "karmaConfig": "karma.conf.js", "watch": false } + }, + "vitest": { + "builder": "@angular/build:unit-test", + "options": { + "runner": "vitest", + "tsConfig": "tsconfig.json", + "providersFile": "src/setup-vitest.ts", + "buildTarget": "a22:build:testing", + "runnerConfig": "vitest.config.ts", + "watch": false + } } } }, diff --git a/e2e/a22/package-lock.json b/e2e/a22/package-lock.json index 3f4571db0b..c48f63c98f 100644 --- a/e2e/a22/package-lock.json +++ b/e2e/a22/package-lock.json @@ -31,6 +31,7 @@ "jest": "30.3.0", "jest-environment-jsdom": "30.3.0", "jest-preset-angular": "16.1.1", + "jsdom": "29.0.0", "karma": "6.4.4", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", @@ -40,7 +41,8 @@ "npm": "11.11.1", "puppeteer": "24.39.1", "ts-node": "10.9.2", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "4.1.0" }, "engines": { "npm": "11.11.1" @@ -653,7 +655,6 @@ "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-color-parser": "^4.0.2", @@ -671,7 +672,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -682,7 +682,6 @@ "integrity": "sha512-Q6mU0Z6bfj6YvnX2k9n0JxiIwrCFN59x/nWmYQnAqP000ruX/yV+5bp/GRcF5T8ncvfwJQ7fgfP74DlpKExILA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", @@ -700,7 +699,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -710,8 +708,7 @@ "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.29.0", @@ -1268,7 +1265,6 @@ "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "css-tree": "^3.0.0" }, @@ -1326,7 +1322,6 @@ } ], "license": "MIT-0", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -1347,7 +1342,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1372,7 +1366,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@csstools/color-helpers": "^6.0.2", "@csstools/css-calc": "^3.1.1" @@ -1401,7 +1394,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1425,7 +1417,6 @@ } ], "license": "MIT-0", - "peer": true, "peerDependencies": { "css-tree": "^3.2.1" }, @@ -1451,7 +1442,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -1938,7 +1928,6 @@ "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, @@ -5132,6 +5121,17 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", @@ -5142,6 +5142,13 @@ "@types/node": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -5570,6 +5577,136 @@ "vite": "^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/expect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.0", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.0", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -5797,6 +5934,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -6084,7 +6231,6 @@ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "require-from-string": "^2.0.2" } @@ -6420,6 +6566,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6995,7 +7151,6 @@ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" @@ -7190,7 +7345,6 @@ "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" @@ -7702,6 +7856,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -7980,6 +8141,16 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/exponential-backoff": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", @@ -8712,7 +8883,6 @@ "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@exodus/bytes": "^1.6.0" }, @@ -10279,7 +10449,6 @@ "integrity": "sha512-9FshNB6OepopZ08unmmGpsF7/qCjxGPbo3NbgfJAnPeHXnsODE9WWffXZtRFRFe0ntzaAOcSKNJFz8wiyvF1jQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/css-color": "^5.0.1", "@asamuzakjp/dom-selector": "^7.0.2", @@ -10321,7 +10490,6 @@ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.12" }, @@ -10335,7 +10503,6 @@ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", - "peer": true, "engines": { "node": "20 || >=22" } @@ -10346,7 +10513,6 @@ "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "entities": "^6.0.0" }, @@ -11433,8 +11599,7 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/media-typer": { "version": "1.1.0", @@ -14182,6 +14347,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -14653,6 +14829,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -15661,6 +15844,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -15985,6 +16175,13 @@ "node": ">=10" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -15995,6 +16192,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.3.1.tgz", @@ -16391,6 +16595,23 @@ "b4a": "^1.6.4" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -16408,13 +16629,22 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { "version": "7.0.25", "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tldts-core": "^7.0.25" }, @@ -16427,8 +16657,7 @@ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tmp": { "version": "0.2.5", @@ -16476,7 +16705,6 @@ "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "tldts": "^7.0.5" }, @@ -16490,7 +16718,6 @@ "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "punycode": "^2.3.1" }, @@ -16504,7 +16731,6 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -16746,7 +16972,6 @@ "integrity": "sha512-eJdUmK/Wrx2d+mnWWmwwLRyA7OQCkLap60sk3dOK4ViZR7DKwwptwuIvFBg2HaiP9ESaEdhtpSymQPvytpmkCA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20.18.1" } @@ -17004,6 +17229,88 @@ } } }, + "node_modules/vitest": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -17072,7 +17379,6 @@ "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=20" } @@ -17110,7 +17416,6 @@ "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" } @@ -17121,7 +17426,6 @@ "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", @@ -17147,6 +17451,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/e2e/a22/package.json b/e2e/a22/package.json index 661a64ee0d..13c1b88e31 100644 --- a/e2e/a22/package.json +++ b/e2e/a22/package.json @@ -7,12 +7,14 @@ "ng": "ng", "start": "ng serve", "build": "ng build", - "test": "npm run test:jasmine && npm run test:jest", + "test": "npm run test:jasmine && npm run test:jest && npm run test:vitest", "test:debug": "npm run test:jasmine:debug", "test:jasmine": "ng test --ts-config ./tsconfig.json --progress=false --no-watch", "test:jasmine:debug": "npm run test:jasmine -- --watch --browsers Chrome", "test:jest": "jest --config jest.config.ts", - "test:jest:debug": "jest -i --watch" + "test:jest:debug": "jest -i --watch", + "test:vitest": "ng run a22:vitest --progress=false --no-watch", + "test:vitest:debug": "npm run test:vitest -- --watch" }, "private": true, "dependencies": { @@ -39,6 +41,7 @@ "jest": "30.3.0", "jest-environment-jsdom": "30.3.0", "jest-preset-angular": "16.1.1", + "jsdom": "29.0.0", "karma": "6.4.4", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", @@ -48,7 +51,8 @@ "npm": "11.11.1", "puppeteer": "24.39.1", "ts-node": "10.9.2", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "4.1.0" }, "engines": { "npm": "11.11.1" diff --git a/e2e/a22/src/setup-vitest.ts b/e2e/a22/src/setup-vitest.ts new file mode 100644 index 0000000000..36fe6b7ab3 --- /dev/null +++ b/e2e/a22/src/setup-vitest.ts @@ -0,0 +1,21 @@ +import { MockService, ngMocks } from 'ng-mocks'; // eslint-disable-line import-x/order + +ngMocks.autoSpy('vitest'); + +// In case, if you use @angular/router and Angular 14+. +// You might want to set a mock of DefaultTitleStrategy as TitleStrategy. +// A14 fix: making DefaultTitleStrategy to be a default mock for TitleStrategy +import { DefaultTitleStrategy, TitleStrategy } from '@angular/router'; // eslint-disable-line import-x/order +ngMocks.defaultMock(TitleStrategy, () => MockService(DefaultTitleStrategy)); + +// Usually, *ngIf and other declarations from CommonModule aren't expected to be mocked. +// The code below keeps them. +import { CommonModule } from '@angular/common'; // eslint-disable-line import-x/order +import { ApplicationModule, provideZoneChangeDetection } from '@angular/core'; // eslint-disable-line import-x/order +import { BrowserModule } from '@angular/platform-browser'; // eslint-disable-line import-x/order +ngMocks.globalKeep(ApplicationModule, true); +ngMocks.globalKeep(CommonModule, true); +ngMocks.globalKeep(BrowserModule, true); + +// Return providers that Angular should setup in the testing environment. +export default [provideZoneChangeDetection()]; diff --git a/e2e/a22/tsconfig.json b/e2e/a22/tsconfig.json index 79e07b8a68..489cf8bedf 100644 --- a/e2e/a22/tsconfig.json +++ b/e2e/a22/tsconfig.json @@ -16,7 +16,7 @@ "target": "ES2022", "module": "preserve", "useDefineForClassFields": false, - "types": ["jasmine", "jest", "node"] + "types": ["jasmine", "jest", "vitest/globals", "node"] }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, @@ -24,6 +24,6 @@ "strictInputAccessModifiers": true, "strictTemplates": true }, - "files": ["src/main.ts", "src/test.ts", "src/setup-jest.ts"], - "include": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] + "files": ["src/main.ts", "src/test.ts", "src/setup-jest.ts", "src/setup-vitest.ts"], + "include": ["jest.config.ts", "vitest.config.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] } diff --git a/e2e/a22/vitest.config.ts b/e2e/a22/vitest.config.ts new file mode 100644 index 0000000000..c4a85d8112 --- /dev/null +++ b/e2e/a22/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + maxConcurrency: 1, + fileParallelism: false, + }, +}); diff --git a/examples/MockActivatedRoute/test.spec.ts b/examples/MockActivatedRoute/test.spec.ts index 46835486c0..d06bdb47ee 100644 --- a/examples/MockActivatedRoute/test.spec.ts +++ b/examples/MockActivatedRoute/test.spec.ts @@ -43,16 +43,26 @@ describe('MockActivatedRoute', () => { it('uses paramId from ActivatedRoute', () => { // Let's set the params of the snapshot. if (typeof jest === 'undefined') { - MockInstance( - ActivatedRoute, - 'snapshot', - jasmine.createSpy(), - 'get', - ).and.returnValue({ - paramMap: new Map([['paramId', 'paramValue']]), - }); + if ('vi' in (window as any)) { + MockInstance( + ActivatedRoute, + 'snapshot', + (window as any).vi.fn(), + 'get', + ).mockReturnValue({ + paramMap: new Map([['paramId', 'paramValue']]), + }); + } else { + MockInstance( + ActivatedRoute, + 'snapshot', + jasmine.createSpy(), + 'get', + ).and.returnValue({ + paramMap: new Map([['paramId', 'paramValue']]), + }); + } } else { - // in case of jest. MockInstance( ActivatedRoute, 'snapshot', @@ -62,6 +72,12 @@ describe('MockActivatedRoute', () => { paramMap: new Map([['paramId', 'paramValue']]), }); } + // in case of jasmine + // MockInstance(ActivatedRoute, 'snapshot', jasmine.createSpy(), 'get').and.returnValue({ paramMap: new Map([['paramId', 'paramValue']]) }); + // in case of jest + // MockInstance(ActivatedRoute, 'snapshot', jest.fn(), 'get').mockReturnValue({ paramMap: new Map([['paramId', 'paramValue']]) }); + // in case of vitest + // MockInstance(ActivatedRoute, 'snapshot', vi.fn(), 'get').mockReturnValue({ paramMap: new Map([['paramId', 'paramValue']]) }); // Rendering RouteComponent. const fixture = MockRender(RouteComponent); diff --git a/examples/MockComponent/test.spec.ts b/examples/MockComponent/test.spec.ts index 68b940b374..b3927fd3a6 100644 --- a/examples/MockComponent/test.spec.ts +++ b/examples/MockComponent/test.spec.ts @@ -93,9 +93,11 @@ describe('MockComponent', () => { ngMocks.stubMember( component, 'trigger', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - // in case of jest - // jest.fn(), + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(), ); mockComponent.someOutput.emit({ payload: 'foo', diff --git a/examples/MockDirective-Attribute/test.spec.ts b/examples/MockDirective-Attribute/test.spec.ts index 2a224599bc..c6154529f3 100644 --- a/examples/MockDirective-Attribute/test.spec.ts +++ b/examples/MockDirective-Attribute/test.spec.ts @@ -96,9 +96,11 @@ describe('MockDirective:Attribute', () => { ngMocks.stubMember( component, 'trigger', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - // in case of jest - // jest.fn(), + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(), ); mockDirective.someOutput.emit(); diff --git a/examples/MockForms/test.spec.ts b/examples/MockForms/test.spec.ts index d4ad41634c..9497443a79 100644 --- a/examples/MockForms/test.spec.ts +++ b/examples/MockForms/test.spec.ts @@ -69,10 +69,16 @@ describe('MockForms', () => { // With auto spy this code is not needed. const writeValue = typeof jest === 'undefined' - ? jasmine.createSpy('writeValue') - : jest.fn(); + ? 'vi' in (window as any) + ? (window as any).vi.fn().mockName('writeValue') + : jasmine.createSpy('writeValue') + : jest.fn().mockName('writeValue'); + // in case of jasmine + // const writeValue = jasmine.createSpy('writeValue'); // in case of jest - // const writeValue = jest.fn(); + // const writeValue = jest.fn().mockName('writeValue'); + // in case of vitest + // const writeValue = vi.fn().mockName('writeValue'); // Because of early calls of writeValue, we need to install // the spy via MockInstance before the render. diff --git a/examples/MockPipe/test.spec.ts b/examples/MockPipe/test.spec.ts index ace711a73f..bb1a2a6f27 100644 --- a/examples/MockPipe/test.spec.ts +++ b/examples/MockPipe/test.spec.ts @@ -39,10 +39,16 @@ describe('MockPipe', () => { // how the pipe has been called. const spy = typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(fakeTransform) + ? 'vi' in (window as any) + ? (window as any).vi.fn(fakeTransform) + : jasmine.createSpy().and.callFake(fakeTransform) : jest.fn(fakeTransform); + // in case of jasmine + // const spy = jasmine.createSpy().and.callFake(fakeTransform); // in case of jest - // const spy = jest.fn().mockImplementation(fakeTransform); + // const spy = jest.fn(fakeTransform); + // in case of vitest + // const spy = vi.fn(fakeTransform); beforeEach(() => { return ( diff --git a/examples/MockReactiveForms/test.spec.ts b/examples/MockReactiveForms/test.spec.ts index ccfb5be169..01cfa31915 100644 --- a/examples/MockReactiveForms/test.spec.ts +++ b/examples/MockReactiveForms/test.spec.ts @@ -68,10 +68,16 @@ describe('MockReactiveForms', () => { // With auto spy this code is not needed. const writeValue = typeof jest === 'undefined' - ? jasmine.createSpy('writeValue') - : jest.fn(); + ? 'vi' in (window as any) + ? (window as any).vi.fn().mockName('writeValue') + : jasmine.createSpy('writeValue') + : jest.fn().mockName('writeValue'); + // in case of jasmine + // const writeValue = jasmine.createSpy('writeValue'); // in case of jest - // const writeValue = jest.fn(); + // const writeValue = jest.fn().mockName('writeValue'); + // in case of vitest + // const writeValue = vi.fn().mockName('writeValue'); // Because of early calls of writeValue, we need to install // the spy via MockInstance before the render. diff --git a/examples/MockRender/test.spec.ts b/examples/MockRender/test.spec.ts index e41a79909e..b88c560524 100644 --- a/examples/MockRender/test.spec.ts +++ b/examples/MockRender/test.spec.ts @@ -55,9 +55,17 @@ describe('MockRender', () => { it('renders template', () => { const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(); + // in case of jasmine + // const spy = jasmine.createSpy(); // in case of jest // const spy = jest.fn(); + // in case of vitest + // const spy = vi.fn(); const fixture = MockRender( ` @@ -92,9 +100,17 @@ describe('MockRender', () => { it('renders inputs and outputs automatically', () => { const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(); + // in case of jasmine + // const spy = jasmine.createSpy(); // in case of jest - // const logoClickSpy = jest.fn(); + // const spy = jest.fn(); + // in case of vitest + // const spy = vi.fn(); // Generates a template like: // { RootService, 'trigger', typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('mock') + ? 'vi' in (window as any) + ? (window as any).vi.fn().mockReturnValue('mock') + : jasmine.createSpy().and.returnValue('mock') : jest.fn().mockReturnValue('mock'), - // or in case of jest - // jest.fn().mockReturnValue('mock'), ); // Rendering the pipe. diff --git a/examples/main/test.spec.ts b/examples/main/test.spec.ts index 472afe612f..1fd966a590 100644 --- a/examples/main/test.spec.ts +++ b/examples/main/test.spec.ts @@ -153,9 +153,17 @@ describe('main', () => { it('asserts behavior of AppComponent', () => { const logoClickSpy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(); + // in case of jasmine + // const logoClickSpy = jasmine.createSpy(); // in case of jest // const logoClickSpy = jest.fn(); + // in case of vitest + // const logoClickSpy = vi.fn(); // Instead of TestBed.createComponent(AppComponent) in beforeEach // MockRender might be used directly in tests. diff --git a/examples/ngMocksFaster/test.spec.ts b/examples/ngMocksFaster/test.spec.ts index 6e9c03e864..91e868cd43 100644 --- a/examples/ngMocksFaster/test.spec.ts +++ b/examples/ngMocksFaster/test.spec.ts @@ -48,10 +48,16 @@ describe('examples:performance', () => { init: instance => { instance.method = typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue(5) + ? 'vi' in (window as any) + ? (window as any).vi.fn().mockReturnValue(5) + : jasmine.createSpy().and.returnValue(5) : jest.fn().mockReturnValue(5); + // in case of jasmine + // instance.method = jasmine.createSpy().and.returnValue(5); // in case of jest // instance.method = jest.fn().mockReturnValue(5); + // in case of vitest + // instance.method = vi.fn().mockReturnValue(5); instance.prop = 123; }, }); @@ -92,22 +98,32 @@ describe('examples:performance', () => { const mock = { method: typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue(5) + ? 'vi' in (window as any) + ? (window as any).vi.fn().mockReturnValue(5) + : jasmine.createSpy().and.returnValue(5) : jest.fn().mockReturnValue(5), + // in case of jasmine + // method: jasmine.createSpy().and.returnValue(5), // in case of jest // method: jest.fn().mockReturnValue(5), + // in case of vitest + // method: vi.fn().mockReturnValue(5), prop: 123, }; // Do not forget to reset the spy between runs. beforeEach(() => { - if (typeof jest === 'undefined') { - (mock.method as jasmine.Spy).calls.reset(); + if (typeof jest === 'undefined' && !('vi' in (window as any))) { + mock.method.calls.reset(); } else { - mock.method = jest.fn().mockReturnValue(5); + mock.method.mockClear(); } + // in case of jasmine + // method: mock.method.calls.reset() // in case of jest - // mock.method = jest.fn().mockReturnValue(5); + // method: mock.method.mockClear(), + // in case of vitest + // method: mock.method.mockClear(), mock.prop = 123; }); diff --git a/examples/readme/builder.spec.ts b/examples/readme/builder.spec.ts index b55efd338d..e8fb71d6b4 100644 --- a/examples/readme/builder.spec.ts +++ b/examples/readme/builder.spec.ts @@ -198,7 +198,11 @@ describe('profile:builder', () => { const spySave = MockInstance( StorageService, 'save', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(), ); // Renders diff --git a/examples/readme/classic.spec.ts b/examples/readme/classic.spec.ts index 316f12bfd5..42cc8f960c 100644 --- a/examples/readme/classic.spec.ts +++ b/examples/readme/classic.spec.ts @@ -155,7 +155,11 @@ describe('profile:classic', () => { const spySave = MockInstance( StorageService, 'save', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + typeof jest === 'undefined' + ? 'vi' in (window as any) + ? (window as any).vi.fn() + : jasmine.createSpy() + : jest.fn(), ); // Renders diff --git a/libs/ng-mocks/package.json b/libs/ng-mocks/package.json index e58be031e7..b959f93eb3 100644 --- a/libs/ng-mocks/package.json +++ b/libs/ng-mocks/package.json @@ -1,7 +1,7 @@ { "name": "ng-mocks", "version": "0.0.0", - "description": "An Angular testing library for creating mock services, components, directives, pipes and modules in unit tests. It provides shallow rendering, precise stubs to fake child dependencies. ng-mocks works with Angular 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22, jasmine and jest.", + "description": "An Angular testing library for creating mock services, components, directives, pipes and modules in unit tests. It provides shallow rendering, precise stubs to fake child dependencies. ng-mocks works with Angular >5, jasmine, jest and vitest.", "keywords": [ "angular", "test", diff --git a/libs/ng-mocks/src/lib/mock-helper/mock-helper.auto-spy.ts b/libs/ng-mocks/src/lib/mock-helper/mock-helper.auto-spy.ts index 82b732bdc0..14f915c80c 100644 --- a/libs/ng-mocks/src/lib/mock-helper/mock-helper.auto-spy.ts +++ b/libs/ng-mocks/src/lib/mock-helper/mock-helper.auto-spy.ts @@ -1,7 +1,8 @@ +import funcGetGlobal from '../common/func.get-global'; import { registerMockFunction } from '../mock-service/helper.mock-service'; import { CustomMockFunction } from '../mock-service/types'; -type param = 'jasmine' | 'jest' | 'default' | 'reset' | CustomMockFunction; +type param = 'jasmine' | 'jest' | 'vitest' | 'default' | 'reset' | CustomMockFunction; const calls: param[] = []; @@ -20,6 +21,11 @@ export default (type: param) => { if (action === 'jest') { return registerMockFunction(name => jest.fn().mockName(name)); } + // istanbul ignore if: because it is run with jasmine + if (action === 'vitest') { + const global = funcGetGlobal(); + return registerMockFunction(name => global.vi.fn().mockName(name)); + } if (!action || action === 'default' || action === 'reset') { return registerMockFunction(); } diff --git a/libs/ng-mocks/src/lib/mock-helper/mock-helper.ts b/libs/ng-mocks/src/lib/mock-helper/mock-helper.ts index cc7d081768..3ab4d359c4 100644 --- a/libs/ng-mocks/src/lib/mock-helper/mock-helper.ts +++ b/libs/ng-mocks/src/lib/mock-helper/mock-helper.ts @@ -23,7 +23,7 @@ export const ngMocks: { * * @see https://ng-mocks.sudo.eu/extra/auto-spy */ - autoSpy(type: 'jasmine' | 'jest' | 'default' | 'reset'): void; + autoSpy(type: 'jasmine' | 'jest' | 'vitest' | 'default' | 'reset'): void; /** * ngMocks.autoSpy installs proper spies instead of empty functions. diff --git a/package-lock.json b/package-lock.json index 98f4a75673..614a6c6382 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,6 +73,7 @@ "ts-node": "10.9.2", "tsconfig-paths-webpack-plugin": "4.2.0", "typescript": "5.9.3", + "vitest": "4.1.0", "webpack": "5.105.4", "webpack-cli": "7.0.1", "zone.js": "0.16.1" @@ -114,9 +115,9 @@ } }, "node_modules/@actions/http-client/node_modules/undici": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", - "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", "dev": true, "license": "MIT", "engines": { @@ -1341,6 +1342,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -1370,9 +1387,9 @@ } }, "node_modules/@jest/diff-sequences": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", - "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", "dev": true, "license": "MIT", "engines": { @@ -1380,9 +1397,9 @@ } }, "node_modules/@jest/expect-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", - "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", "dev": true, "license": "MIT", "dependencies": { @@ -1430,9 +1447,9 @@ } }, "node_modules/@jest/types": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", - "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", "dev": true, "license": "MIT", "dependencies": { @@ -2029,6 +2046,26 @@ "url": "https://github.com/sponsors/ota-meshi" } }, + "node_modules/@oxc-project/runtime": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", + "integrity": "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.115.0.tgz", + "integrity": "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@package-json/types": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@package-json/types/-/types-0.0.12.tgz", @@ -2127,6 +2164,303 @@ "node": ">=18" } }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz", + "integrity": "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz", + "integrity": "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz", + "integrity": "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==", + "dev": true, + "license": "MIT" + }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", @@ -2657,6 +2991,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@semantic-release/release-notes-generator/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/release-notes-generator/node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", @@ -2802,6 +3149,17 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/concat-stream": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-2.0.3.tgz", @@ -2849,6 +3207,13 @@ "@types/ms": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -3154,16 +3519,6 @@ "node": ">= 12" } }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/yargs": { "version": "17.0.35", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", @@ -3531,6 +3886,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3545,6 +3903,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3559,6 +3920,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3573,6 +3937,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3587,6 +3954,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3601,6 +3971,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3694,6 +4067,126 @@ "win32" ] }, + "node_modules/@vitest/expect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.0", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.0", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -4151,6 +4644,16 @@ "node": ">=0.8" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -4338,9 +4841,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.8", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", - "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4591,9 +5094,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001779", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001779.tgz", - "integrity": "sha512-U5og2PN7V4DMgF50YPNtnZJGWVLFjjsN3zb6uMT5VGYIewieDj1upwfuVNXf4Kor+89c3iCRJnSzMD5LmTvsfA==", + "version": "1.0.30001775", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", + "integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==", "dev": true, "funding": [ { @@ -4629,6 +5132,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4856,16 +5369,6 @@ "npm": ">=5.0.0" } }, - "node_modules/cli-highlight/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cli-highlight/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -4903,19 +5406,6 @@ "node": ">=8" } }, - "node_modules/cli-highlight/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cli-highlight/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -4979,16 +5469,6 @@ "@colors/colors": "1.5.0" } }, - "node_modules/cli-table3/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5014,19 +5494,6 @@ "node": ">=8" } }, - "node_modules/cli-table3/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cli-truncate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", @@ -5049,24 +5516,14 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, "engines": { - "node": ">=8" + "node": ">=12" } }, "node_modules/cliui/node_modules/is-fullwidth-code-point": { @@ -5094,19 +5551,6 @@ "node": ">=8" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -5342,9 +5786,9 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.0.tgz", - "integrity": "sha512-DOuBwYSqWzfwuRByY9O4oOIvDlkUCTDzfbOgcSbkY+imXXj+4tmrEFao3K+FxemClYfYnZzsvudbwrhje9VHDA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.2.0.tgz", + "integrity": "sha512-4YB1zEXqB17oBI8yRsAs1T+ZhbdsOgJqkl6Trz+GXt/eKf1e4jnA0oW+sOd9BEENzEViuNW0DNoFFjSf3CeC5Q==", "dev": true, "license": "ISC", "dependencies": { @@ -5355,9 +5799,9 @@ } }, "node_modules/conventional-changelog-conventionalcommits": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.0.tgz", - "integrity": "sha512-kYFx6gAyjSIMwNtASkI3ZE99U1fuVDJr0yTYgVy+I2QG46zNZfl2her+0+eoviG82c5WQvW1jMt1eOQTeJLodA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.2.0.tgz", + "integrity": "sha512-fCf+ODjseueTV09wVBoC0HXLi3OyuBJ+HfE3L63Khxqnr99f9nUcnQh3a15lCWHlGLihyZShW/mVVkBagr9JvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -5368,9 +5812,9 @@ } }, "node_modules/conventional-changelog-writer": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.4.0.tgz", - "integrity": "sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.3.0.tgz", + "integrity": "sha512-l5hDOHjcTUVtnZJapoqXMCJ3IbyF6oV/vnxKL13AHulFH7mDp4PMJARxI7LWzob6UDDvhxIUWGTNUPW84JabQg==", "dev": true, "license": "MIT", "dependencies": { @@ -5815,6 +6259,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -5970,9 +6424,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.313", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", - "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", "dev": true, "license": "ISC" }, @@ -6021,15 +6475,14 @@ } }, "node_modules/engine.io": { - "version": "6.6.6", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.6.tgz", - "integrity": "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA==", + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", + "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", "dev": true, "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", - "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", @@ -7106,6 +7559,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -7171,23 +7634,33 @@ } }, "node_modules/expect": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", - "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.3.0", + "@jest/expect-utils": "30.2.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -7504,9 +7977,9 @@ } }, "node_modules/flatted": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", - "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", + "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", "dev": true, "license": "ISC" }, @@ -7585,9 +8058,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, "license": "MIT", "dependencies": { @@ -7786,6 +8259,16 @@ "traverse": "0.6.8" } }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~2.0.0" + } + }, "node_modules/git-raw-commits": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", @@ -8085,9 +8568,9 @@ } }, "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", - "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -8706,13 +9189,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, "node_modules/isbinaryfile": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", @@ -8951,51 +9427,51 @@ } }, "node_modules/jest-diff": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", - "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.3.0", + "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.3.0" + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", - "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.3.0", - "pretty-format": "30.3.0" + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-message-util": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", - "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.3.0", + "@jest/types": "30.2.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3", - "pretty-format": "30.3.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -9003,29 +9479,16 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-message-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/jest-mock": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", - "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.2.0", "@types/node": "*", - "jest-util": "30.3.0" + "jest-util": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -9042,18 +9505,18 @@ } }, "node_modules/jest-util": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", - "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3" + "picomatch": "^4.0.2" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -9485,16 +9948,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/karma/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/karma/node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -9576,19 +10029,6 @@ "node": ">=8" } }, - "node_modules/karma/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/karma/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -9636,48 +10076,321 @@ "node": ">=10" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "lcov-parse": "bin/cli.js" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", - "bin": { - "lcov-parse": "bin/cli.js" + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.8.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/lines-and-columns": { @@ -9997,6 +10710,22 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/log4js": { "version": "6.9.1", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", @@ -10049,6 +10778,16 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-asynchronous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/make-asynchronous/-/make-asynchronous-1.1.0.tgz", @@ -10067,6 +10806,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-asynchronous/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -11120,6 +11872,25 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-postinstall": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", @@ -11215,9 +11986,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, @@ -13402,6 +14173,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -13691,6 +14473,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", @@ -13809,6 +14604,13 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -14019,6 +14821,35 @@ "node": ">=4" } }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -14059,9 +14890,9 @@ } }, "node_modules/pretty-format": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", - "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", "dependencies": { @@ -14481,6 +15312,13 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, "node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -14773,6 +15611,40 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rolldown": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", + "integrity": "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.115.0", + "@rolldown/pluginutils": "1.0.0-rc.9" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-x64": "1.0.0-rc.9", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" + } + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -15060,6 +15932,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semantic-release/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/semantic-release/node_modules/yargs": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", @@ -15233,6 +16121,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -15522,6 +16417,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -15576,16 +16481,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/split2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", - "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", - "dev": true, - "license": "ISC", - "dependencies": { - "through2": "~2.0.0" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -15652,6 +16547,13 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -15662,6 +16564,13 @@ "node": ">= 0.6" } }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", @@ -15805,16 +16714,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -15825,17 +16724,20 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/stringify-entities": { @@ -15854,19 +16756,16 @@ } }, "node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-ansi-cjs": { @@ -15893,6 +16792,16 @@ "node": ">=8" } }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -16235,9 +17144,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.3.17", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", + "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", "dev": true, "license": "MIT", "dependencies": { @@ -16355,6 +17264,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyexec": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", @@ -16413,6 +17329,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", @@ -16589,21 +17515,6 @@ } } }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tsconfig-paths-webpack-plugin": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", @@ -16620,6 +17531,21 @@ "node": ">=10.13.0" } }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -16670,19 +17596,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -16767,9 +17680,9 @@ } }, "node_modules/undici": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.3.tgz", - "integrity": "sha512-eJdUmK/Wrx2d+mnWWmwwLRyA7OQCkLap60sk3dOK4ViZR7DKwwptwuIvFBg2HaiP9ESaEdhtpSymQPvytpmkCA==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", "dev": true, "license": "MIT", "engines": { @@ -16861,9 +17774,9 @@ } }, "node_modules/unified-engine/node_modules/@types/node": { - "version": "22.19.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", - "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "version": "22.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz", + "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==", "dev": true, "license": "MIT", "dependencies": { @@ -17385,6 +18298,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/vfile-reporter/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/vfile-reporter/node_modules/supports-color": { "version": "9.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", @@ -17428,6 +18357,193 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vite": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0.tgz", + "integrity": "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/runtime": "0.115.0", + "lightningcss": "^1.32.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.9", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.0.0-alpha.31", + "esbuild": "^0.27.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -17725,6 +18841,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -17786,16 +18919,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -17821,19 +18944,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", @@ -17872,6 +18982,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -18013,16 +19139,6 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -18048,19 +19164,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 819f938ce3..a790bc59d1 100644 --- a/package.json +++ b/package.json @@ -218,8 +218,8 @@ "test:a18": "cd e2e/a18 && npm run test:jasmine && npm run test:jest", "test:a19": "cd e2e/a19 && npm run test:jasmine && npm run test:jest", "test:a20": "cd e2e/a20 && npm run test:jasmine && npm run test:jest", - "test:a21": "cd e2e/a21 && npm run test:jasmine && npm run test:jest", - "test:a22": "cd e2e/a22 && npm run test:jasmine && npm run test:jest", + "test:a21": "cd e2e/a21 && npm run test:jasmine && npm run test:jest && npm run test:vitest", + "test:a22": "cd e2e/a22 && npm run test:jasmine && npm run test:jest && npm run test:vitest", "test:jasmine": "cd e2e/jasmine && npm run test:jasmine", "test:jest": "cd e2e/jest && npm run test:jest", "test:min": "cd e2e/min && npm run test:jasmine", @@ -321,7 +321,8 @@ "typescript": "5.9.3", "webpack": "5.105.4", "webpack-cli": "7.0.1", - "zone.js": "0.16.1" + "zone.js": "0.16.1", + "vitest": "4.1.0" }, "engines": { "npm": "11.11.1" diff --git a/tests/control-value-accessor-form-control/test.spec.ts b/tests/control-value-accessor-form-control/test.spec.ts index 54aa1f00fc..64a991a65e 100644 --- a/tests/control-value-accessor-form-control/test.spec.ts +++ b/tests/control-value-accessor-form-control/test.spec.ts @@ -14,6 +14,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock, handleMockProcessor } from '../mock-helpers'; + @Component({ selector: 'target-cva-form-control', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -88,16 +90,12 @@ describe('control-value-accessor-form-control:real', () => { ngMocks.stubMember( mock, 'writeValue', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.writeValue) - : jest.fn(mock.writeValue), + createMock(mock.writeValue), ); ngMocks.stubMember( mock, 'setDisabledState', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.setDisabledState) - : jest.fn(mock.setDisabledState), + createMock(mock.setDisabledState), ); fixture.detectChanges(); @@ -168,30 +166,22 @@ describe('control-value-accessor-form-control:mock', () => { ngMocks.stubMember( mock, 'writeValue', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.writeValue) - : jest.fn(mock.writeValue), + createMock(mock.writeValue), ); ngMocks.stubMember( mock, 'setDisabledState', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.setDisabledState) - : jest.fn(mock.setDisabledState), + createMock(mock.setDisabledState), ); ngMocks.stubMember( mock, 'registerOnChange', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.registerOnChange) - : jest.fn(mock.registerOnChange), + createMock(mock.registerOnChange), ); ngMocks.stubMember( mock, 'registerOnTouched', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.registerOnTouched) - : jest.fn(mock.registerOnTouched), + createMock(mock.registerOnTouched), ); fixture.detectChanges(); @@ -223,14 +213,21 @@ describe('control-value-accessor-form-control:mock', () => { fixture.point.componentInstance.control.touched, ).toBeFalsy(); // a way through a spy - if (typeof jest === 'undefined') { - ngMocks - .stub(mock, 'registerOnTouched') - .calls.first() - .args[0](); - } else { - ngMocks.stub(mock, 'registerOnTouched').mock.calls[0][0](); - } + handleMockProcessor({ + jasmine: () => + ngMocks + .stub(mock, 'registerOnTouched') + .calls.first() + .args[0](), + jest: () => + ngMocks + .stub(mock, 'registerOnTouched') + .mock.calls[0][0](), + vitest: () => + ngMocks + .stub(mock, 'registerOnTouched') + .mock.calls[0][0](), + }); expect( fixture.point.componentInstance.control.touched, ).toBeTruthy(); @@ -254,16 +251,21 @@ describe('control-value-accessor-form-control:mock', () => { 'test3', ); // a way through a spy - if (typeof jest === 'undefined') { - ngMocks - .stub(mock, 'registerOnChange') - .calls.first() - .args[0]('test4'); - } else { - ngMocks - .stub(mock, 'registerOnChange') - .mock.calls[0][0]('test4'); - } + handleMockProcessor({ + jasmine: () => + ngMocks + .stub(mock, 'registerOnChange') + .calls.first() + .args[0]('test4'), + jest: () => + ngMocks + .stub(mock, 'registerOnChange') + .mock.calls[0][0]('test4'), + vitest: () => + ngMocks + .stub(mock, 'registerOnChange') + .mock.calls[0][0]('test4'), + }); expect(mock.writeValue).not.toHaveBeenCalledWith('test4'); expect( fixture.point.componentInstance.control.touched, diff --git a/tests/control-value-accessor-ng-model/test.spec.ts b/tests/control-value-accessor-ng-model/test.spec.ts index b0c56e45f8..a465d0caca 100644 --- a/tests/control-value-accessor-ng-model/test.spec.ts +++ b/tests/control-value-accessor-ng-model/test.spec.ts @@ -14,6 +14,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock, handleMockProcessor } from '../mock-helpers'; + @Component({ selector: 'target-cva-ng-model', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -98,16 +100,12 @@ describe('control-value-accessor-ng-model:real', () => { ngMocks.stubMember( mock, 'writeValue', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.writeValue) - : jest.fn(mock.writeValue), + createMock(mock.writeValue), ); ngMocks.stubMember( mock, 'setDisabledState', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.setDisabledState) - : jest.fn(mock.setDisabledState), + createMock(mock.setDisabledState), ); const ngModel = ngMocks.get(mockElement, NgModel); fixture.detectChanges(); @@ -173,30 +171,22 @@ describe('control-value-accessor-ng-model:mock', () => { ngMocks.stubMember( mock, 'writeValue', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.writeValue) - : jest.fn(mock.writeValue), + createMock(mock.writeValue), ); ngMocks.stubMember( mock, 'setDisabledState', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.setDisabledState) - : jest.fn(mock.setDisabledState), + createMock(mock.setDisabledState), ); ngMocks.stubMember( mock, 'registerOnChange', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.registerOnChange) - : jest.fn(mock.registerOnChange), + createMock(mock.registerOnChange), ); ngMocks.stubMember( mock, 'registerOnTouched', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(mock.registerOnTouched) - : jest.fn(mock.registerOnTouched), + createMock(mock.registerOnTouched), ); const ngModel = ngMocks.get(mockElement, NgModel); fixture.detectChanges(); @@ -224,14 +214,21 @@ describe('control-value-accessor-ng-model:mock', () => { ngModel.control.markAsUntouched(); expect(ngModel.touched).toBeFalsy(); // a way through a spy - if (typeof jest === 'undefined') { - ngMocks - .stub(mock, 'registerOnTouched') - .calls.first() - .args[0](); - } else { - ngMocks.stub(mock, 'registerOnTouched').mock.calls[0][0](); - } + handleMockProcessor({ + jasmine: () => + ngMocks + .stub(mock, 'registerOnTouched') + .calls.first() + .args[0](), + jest: () => + ngMocks + .stub(mock, 'registerOnTouched') + .mock.calls[0][0](), + vitest: () => + ngMocks + .stub(mock, 'registerOnTouched') + .mock.calls[0][0](), + }); expect(ngModel.touched).toBeTruthy(); ngModel.control.markAsUntouched(); @@ -253,16 +250,21 @@ describe('control-value-accessor-ng-model:mock', () => { expect(ngModel.touched).toBeFalsy(); expect(fixture.point.componentInstance.value).toBe('test3'); // a way through a spy - if (typeof jest === 'undefined') { - ngMocks - .stub(mock, 'registerOnChange') - .calls.first() - .args[0]('test4'); - } else { - ngMocks - .stub(mock, 'registerOnChange') - .mock.calls[0][0]('test4'); - } + handleMockProcessor({ + jasmine: () => + ngMocks + .stub(mock, 'registerOnChange') + .calls.first() + .args[0]('test4'), + jest: () => + ngMocks + .stub(mock, 'registerOnChange') + .mock.calls[0][0]('test4'), + vitest: () => + ngMocks + .stub(mock, 'registerOnChange') + .mock.calls[0][0]('test4'), + }); expect(mock.writeValue).not.toHaveBeenCalledWith('test4'); expect(ngModel.touched).toBeFalsy(); expect(ngModel.value).toBe('test4'); diff --git a/tests/fake-async/test.spec.ts b/tests/fake-async/test.spec.ts index e499fa8b58..a04fc6a07c 100644 --- a/tests/fake-async/test.spec.ts +++ b/tests/fake-async/test.spec.ts @@ -9,6 +9,8 @@ import { fakeAsync, tick } from '@angular/core/testing'; import { MockBuilder, MockRenderFactory, ngMocks } from 'ng-mocks'; +import funcHasVitest from '../func.has-vitest'; + @Component({ selector: 'target-fake-async', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -38,6 +40,16 @@ class TargetComponent implements OnInit, OnDestroy { // The goal is to ensure that nothing is broken with fakeAsync. describe('fake-async', () => { + if (funcHasVitest()) { + // Angular has completely dropped support for fakeAsync when + // using vitest. So we have to skip all tests in this case. + it('skips tests because of vitest', () => { + expect(true).toBeTruthy(); + }); + + return; + } + let calls = 0; const factory = MockRenderFactory(TargetComponent, ['value']); diff --git a/tests/func.get-vitest.ts b/tests/func.get-vitest.ts new file mode 100644 index 0000000000..366f4dc424 --- /dev/null +++ b/tests/func.get-vitest.ts @@ -0,0 +1,8 @@ +declare const vi: any; +export default () => { + try { + return vi; + } catch { + return undefined; + } +}; diff --git a/tests/func.has-vitest.ts b/tests/func.has-vitest.ts new file mode 100644 index 0000000000..f0427b752e --- /dev/null +++ b/tests/func.has-vitest.ts @@ -0,0 +1,5 @@ +import funcGetVitest from './func.get-vitest'; + +export default () => { + return !!funcGetVitest(); +}; diff --git a/tests/get-inputs-and-outputs/test.spec.ts b/tests/get-inputs-and-outputs/test.spec.ts index 6f7c35c592..2225b3bc8e 100644 --- a/tests/get-inputs-and-outputs/test.spec.ts +++ b/tests/get-inputs-and-outputs/test.spec.ts @@ -1,5 +1,7 @@ import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + import { Target2Directive, Target3Directive, @@ -14,22 +16,13 @@ describe('get-inputs-and-outputs', () => { const params = { input1: '1', input2: '2', - output1: - typeof jest === 'undefined' - ? jasmine.createSpy('output1') - : jest.fn().mockName('output1'), + output1: createMock('output1'), // in case of jest // output1: jest.fn().mockName('output1'), - output2: - typeof jest === 'undefined' - ? jasmine.createSpy('output2') - : jest.fn().mockName('output2'), + output2: createMock('output2'), // in case of jest // output2: jest.fn().mockName('output2'), - output3: - typeof jest === 'undefined' - ? jasmine.createSpy('output3') - : jest.fn().mockName('output3'), + output3: createMock('output3'), // in case of jest // output3: jest.fn().mockName('output3'), }; diff --git a/tests/issue-10960/test.spec.ts b/tests/issue-10960/test.spec.ts index cba9411115..e0988be801 100644 --- a/tests/issue-10960/test.spec.ts +++ b/tests/issue-10960/test.spec.ts @@ -14,6 +14,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + // This standalone CVA is the minimal reproduction of the reported issue: // - it imports ReactiveFormsModule by itself // - it provides NG_VALUE_ACCESSOR via useExisting + forwardRef to itself @@ -104,10 +106,7 @@ describe('issue-10960', () => { ); it('keeps the standalone value accessor intact', () => { - const writeValue = - typeof jest === 'undefined' - ? jasmine.createSpy('writeValue') - : jest.fn(); + const writeValue = createMock('writeValue'); // We spy on writeValue instead of asserting DOM details so that the test // stays focused on the value-accessor handshake: diff --git a/tests/issue-162/test.spec.ts b/tests/issue-162/test.spec.ts index 45bc3c0365..24ba6e4a9e 100644 --- a/tests/issue-162/test.spec.ts +++ b/tests/issue-162/test.spec.ts @@ -7,6 +7,9 @@ import { import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import funcGetVitest from '../func.get-vitest'; +import { handleMockProcessor } from '../mock-helpers'; + @Component({ selector: 'app-root-162', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -70,43 +73,47 @@ describe('issue-162', () => { let setSpy: any; // creating spies - if (typeof jest === 'undefined') { - getSpy = spyOnProperty( - fixture.point.componentInstance, - 'title', - 'get', - ); - setSpy = spyOnProperty( - fixture.point.componentInstance, - 'title', - 'set', - ); - getSpy.and.returnValue('spy'); - } else { - getSpy = jest.spyOn( - fixture.point.componentInstance, - 'title', - 'get', - ); - setSpy = jest.spyOn( - fixture.point.componentInstance, - 'title', - 'set', - ); - getSpy.mockReturnValue('spy'); - } - // in case of jest - // getSpy = jest.spyOn( - // fixture.point.componentInstance, - // 'title', - // 'get', - // ); - // setSpy = jest.spyOn( - // fixture.point.componentInstance, - // 'title', - // 'set', - // ); - // getSpy.mockReturnValue('spy'); + handleMockProcessor({ + jasmine: () => { + getSpy = spyOnProperty( + fixture.point.componentInstance, + 'title', + 'get', + ); + setSpy = spyOnProperty( + fixture.point.componentInstance, + 'title', + 'set', + ); + getSpy.and.returnValue('spy'); + }, + jest: () => { + getSpy = jest.spyOn( + fixture.point.componentInstance, + 'title', + 'get', + ); + setSpy = jest.spyOn( + fixture.point.componentInstance, + 'title', + 'set', + ); + getSpy.mockReturnValue('spy'); + }, + vitest: () => { + getSpy = funcGetVitest().spyOn( + fixture.point.componentInstance, + 'title', + 'get', + ); + setSpy = funcGetVitest().spyOn( + fixture.point.componentInstance, + 'title', + 'set', + ); + getSpy.mockReturnValue('spy'); + }, + }); expect(fixture.point.componentInstance.title).toEqual('spy'); fixture.point.componentInstance.title = 'updated'; diff --git a/tests/issue-166/test.spec.ts b/tests/issue-166/test.spec.ts index 121ad55094..f4adf8ea55 100644 --- a/tests/issue-166/test.spec.ts +++ b/tests/issue-166/test.spec.ts @@ -2,6 +2,8 @@ import { Observable, Subject } from 'rxjs'; import { MockService, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + class MyService { public readonly onErrorSet$?: Observable; public readonly onSuccessSet$?: Observable; @@ -21,8 +23,7 @@ class MyService { // @see https://github.com/help-me-mom/ng-mocks/issues/166 describe('issue-166', () => { it('accepts spies', () => { - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); // in case of jest // const spy = jest.fn(); const stub = ngMocks.stub(MockService(MyService), { diff --git a/tests/issue-167/component.spec.ts b/tests/issue-167/component.spec.ts index 3a01e318b6..279acc22ba 100644 --- a/tests/issue-167/component.spec.ts +++ b/tests/issue-167/component.spec.ts @@ -12,6 +12,8 @@ import { import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + @Component({ providers: [ { @@ -103,19 +105,9 @@ describe('issue-167:component:real', () => { ngMocks.stubMember( mock, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - updated: true, - }) - : jest.fn().mockReturnValue({ - updated: true, - }), - ); - ngMocks.stubMember( - mock, - 'writeValue', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + mockReturnValue(createMock(), { updated: true }), ); + ngMocks.stubMember(mock, 'writeValue', createMock()); fixture.point.componentInstance.control.setValue('updated'); expect(mock.validate).toHaveBeenCalled(); @@ -144,19 +136,9 @@ describe('issue-167:component:mock', () => { ngMocks.stubMember( mock, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - updated: true, - }) - : jest.fn().mockReturnValue({ - updated: true, - }), - ); - ngMocks.stubMember( - mock, - 'writeValue', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + mockReturnValue(createMock(), { updated: true }), ); + ngMocks.stubMember(mock, 'writeValue', createMock()); fixture.point.componentInstance.control.setValue('updated'); expect(mock.validate).toHaveBeenCalled(); diff --git a/tests/issue-167/directive.spec.ts b/tests/issue-167/directive.spec.ts index 67e7db5d25..db501a7ed1 100644 --- a/tests/issue-167/directive.spec.ts +++ b/tests/issue-167/directive.spec.ts @@ -17,6 +17,8 @@ import { import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + @Directive({ providers: [ { @@ -106,19 +108,9 @@ describe('issue-167:directive:real', () => { ngMocks.stubMember( mock, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - updated: true, - }) - : jest.fn().mockReturnValue({ - updated: true, - }), - ); - ngMocks.stubMember( - mock, - 'writeValue', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + mockReturnValue(createMock(), { updated: true }), ); + ngMocks.stubMember(mock, 'writeValue', createMock()); fixture.point.componentInstance.control.setValue('updated'); expect(mock.validate).toHaveBeenCalled(); @@ -146,19 +138,9 @@ describe('issue-167:directive:mock', () => { ngMocks.stubMember( mock, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - updated: true, - }) - : jest.fn().mockReturnValue({ - updated: true, - }), - ); - ngMocks.stubMember( - mock, - 'writeValue', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + mockReturnValue(createMock(), { updated: true }), ); + ngMocks.stubMember(mock, 'writeValue', createMock()); fixture.point.componentInstance.control.setValue('updated'); expect(mock.validate).toHaveBeenCalled(); diff --git a/tests/issue-167/ng-validators.spec.ts b/tests/issue-167/ng-validators.spec.ts index d5d489bfb5..7bf2299f01 100644 --- a/tests/issue-167/ng-validators.spec.ts +++ b/tests/issue-167/ng-validators.spec.ts @@ -15,6 +15,8 @@ import { import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + @Directive({ providers: [ { @@ -95,13 +97,7 @@ describe('issue-167:NG_VALIDATORS:mock', () => { ngMocks.stubMember( mock, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - mock: true, - }) - : jest.fn().mockReturnValue({ - mock: true, - }), + mockReturnValue(createMock(), { mock: true }), ); fixture.point.componentInstance.control.setValue('updated'); diff --git a/tests/issue-240/test.classic.spec.ts b/tests/issue-240/test.classic.spec.ts index f11a7dba31..251ab53fbb 100644 --- a/tests/issue-240/test.classic.spec.ts +++ b/tests/issue-240/test.classic.spec.ts @@ -2,6 +2,8 @@ import { TestBed } from '@angular/core/testing'; import { MockPipe, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + import { ImpurePipe, PurePipe } from './fixtures'; // @see https://github.com/help-me-mom/ng-mocks/issues/240 @@ -47,16 +49,8 @@ describe('issue-240:classic', () => { // We do not have auto-spies, because we provided callbacks. // Now we need to install spies. - ngMocks.stubMember( - pure, - 'transform', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); - ngMocks.stubMember( - impure, - 'transform', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); + ngMocks.stubMember(pure, 'transform', createMock()); + ngMocks.stubMember(impure, 'transform', createMock()); expect(pure.transform).toHaveBeenCalledTimes(0); expect(impure.transform).toHaveBeenCalledTimes(0); diff --git a/tests/issue-240/test.real.spec.ts b/tests/issue-240/test.real.spec.ts index c35882c2a7..d069ed9388 100644 --- a/tests/issue-240/test.real.spec.ts +++ b/tests/issue-240/test.real.spec.ts @@ -2,6 +2,8 @@ import { TestBed } from '@angular/core/testing'; import { MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + import { ImpurePipe, PurePipe } from './fixtures'; // @see https://github.com/help-me-mom/ng-mocks/issues/240 @@ -23,16 +25,8 @@ describe('issue-240:real', () => { const pure = ngMocks.findInstance(PurePipe); const impure = ngMocks.findInstance(ImpurePipe); - ngMocks.stubMember( - pure, - 'transform', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); - ngMocks.stubMember( - impure, - 'transform', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); + ngMocks.stubMember(pure, 'transform', createMock()); + ngMocks.stubMember(impure, 'transform', createMock()); expect(pure.transform).toHaveBeenCalledTimes(0); expect(impure.transform).toHaveBeenCalledTimes(0); diff --git a/tests/issue-246/test.spec.ts b/tests/issue-246/test.spec.ts index c81b89b300..9c6b2069aa 100644 --- a/tests/issue-246/test.spec.ts +++ b/tests/issue-246/test.spec.ts @@ -20,6 +20,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + @Component({ providers: [ { @@ -148,9 +150,7 @@ describe('issue-246:real', () => { ngMocks.stubMember( ngMocks.findInstance(TargetDirective), 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue(null) - : jest.fn().mockReturnValue(null), + mockReturnValue(createMock(), null), ); control.updateValueAndValidity(); await fixture.whenStable(); @@ -219,17 +219,12 @@ describe('issue-246:mock', () => { ngMocks.stubMember( directiveAsync, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue( - Promise.resolve({ - targetAsync: true, - }), - ) - : jest.fn().mockReturnValue( - Promise.resolve({ - targetAsync: true, - }), - ), + mockReturnValue( + createMock(), + Promise.resolve({ + targetAsync: true, + }), + ), ); directiveAsync.__simulateValidatorChange(); } @@ -243,13 +238,7 @@ describe('issue-246:mock', () => { ngMocks.stubMember( directive, 'validate', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue({ - test: true, - }) - : jest.fn().mockReturnValue({ - test: true, - }), + mockReturnValue(createMock(), { test: true }), ); directive.__simulateValidatorChange(); } diff --git a/tests/issue-2647/ignore.spec.ts b/tests/issue-2647/ignore.spec.ts index 7c2ee6e913..bb495b2575 100644 --- a/tests/issue-2647/ignore.spec.ts +++ b/tests/issue-2647/ignore.spec.ts @@ -10,6 +10,8 @@ import { import { MockBuilder, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + // @TODO remove with A5 support const injectableRootServiceArgs = [ { @@ -115,8 +117,7 @@ describe('issue-2647:ignore', () => { beforeAll(() => (consoleWarn = console.warn)); beforeEach(() => { - console.warn = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + console.warn = createMock(); }); afterAll(() => { diff --git a/tests/issue-2647/warn.spec.ts b/tests/issue-2647/warn.spec.ts index 4915775f66..e80613f172 100644 --- a/tests/issue-2647/warn.spec.ts +++ b/tests/issue-2647/warn.spec.ts @@ -10,6 +10,8 @@ import { import { MockBuilder, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + // @TODO remove with A5 support const injectableRootServiceArgs = [ { @@ -113,8 +115,7 @@ describe('issue-2647:warn', () => { beforeAll(() => (consoleWarn = console.warn)); beforeEach(() => { - console.warn = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + console.warn = createMock(); }); afterAll(() => { diff --git a/tests/issue-305/overrides.spec.ts b/tests/issue-305/overrides.spec.ts index a59de0cc38..7216ebb7a1 100644 --- a/tests/issue-305/overrides.spec.ts +++ b/tests/issue-305/overrides.spec.ts @@ -7,6 +7,8 @@ import { import { MockBuilder, MockInstance, MockRender } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-305-overrides', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -36,14 +38,10 @@ describe('issue-305:overrides', () => { ); it('correctly overrides CVA', () => { - const registerOnChange = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); - const registerOnTouched = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); - const setDisabledState = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); - const writeValue = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const registerOnChange = createMock(); + const registerOnTouched = createMock(); + const setDisabledState = createMock(); + const writeValue = createMock(); MockInstance(DefaultValueAccessor, () => ({ registerOnChange, diff --git a/tests/issue-3265/test.spec.ts b/tests/issue-3265/test.spec.ts index d110dabee5..92cb704ce9 100644 --- a/tests/issue-3265/test.spec.ts +++ b/tests/issue-3265/test.spec.ts @@ -2,6 +2,8 @@ import { Injectable } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Injectable() class SomeService { someMethod(x: string) { @@ -22,11 +24,7 @@ class ServiceToTest { describe('issue-3265', () => { beforeEach(() => MockBuilder(ServiceToTest, SomeService).mock(SomeService, { - someMethod: - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake((x: string) => x) - : // in case of jest - jest.fn((x: string) => x), + someMethod: createMock((x: string) => x), }), ); diff --git a/tests/issue-434/test.spec.ts b/tests/issue-434/test.spec.ts index 8f057d10ca..53e7f51286 100644 --- a/tests/issue-434/test.spec.ts +++ b/tests/issue-434/test.spec.ts @@ -7,6 +7,8 @@ import { import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-434', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -46,8 +48,7 @@ describe('issue-434', () => { it('sets the prop to a value', () => { const fixture = MockRender(TargetComponent, { prop1: 'mock', - update: - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + update: createMock(), }); expect(ngMocks.formatText(fixture)).toEqual('mock:default2'); }); @@ -64,20 +65,13 @@ describe('issue-434', () => { ); // let's set cross spies - fixture.componentInstance.echo1 = - typeof jest === 'undefined' - ? jasmine - .createSpy() - .and.callFake(fixture.componentInstance.echo1) - : jest.fn(fixture.componentInstance.echo1); + fixture.componentInstance.echo1 = createMock( + fixture.componentInstance.echo1, + ); ngMocks.stubMember( fixture.point.componentInstance, 'echo2', - typeof jest === 'undefined' - ? jasmine - .createSpy() - .and.callFake(fixture.point.componentInstance.echo2) - : jest.fn(fixture.point.componentInstance.echo2), + createMock(fixture.point.componentInstance.echo2), ); // a call on the pointer should be reflected in the wrapper diff --git a/tests/issue-455/abstract.spec.ts b/tests/issue-455/abstract.spec.ts index 9ef43d8f84..64128e1826 100644 --- a/tests/issue-455/abstract.spec.ts +++ b/tests/issue-455/abstract.spec.ts @@ -13,6 +13,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + interface InjectedAbstraction { (): string; hello: () => number; @@ -23,11 +25,9 @@ const injectableArgs = [ { providedIn: 'root', useFactory: () => { - const fn: InjectedAbstraction = (typeof jest === 'undefined' - ? jasmine.createSpy() - : jest.fn()) as any as InjectedAbstraction; - fn.hello = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const fn: InjectedAbstraction = + createMock() as any as InjectedAbstraction; + fn.hello = createMock(); return fn; }, @@ -59,9 +59,10 @@ class TestWithDecoratorComponent { } ngMocks.defaultMock(InjectedAbstraction, () => { - return (typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('FOO') - : jest.fn().mockReturnValue('FOO')) as any as InjectedAbstraction; + return mockReturnValue( + createMock(), + 'FOO', + ) as any as InjectedAbstraction; }); // @see https://github.com/help-me-mom/ng-mocks/issues/455 @@ -110,12 +111,10 @@ describe('issue-455:abstract', () => { describe('using explicit mock', () => { describe('without `precise` flag', () => { - const spy = - typeof jest === 'undefined' - ? jasmine - .createSpy('InjectedAbstraction') - .and.returnValue('BAR') - : jest.fn().mockReturnValue('BAR'); + const spy = mockReturnValue( + createMock('InjectedAbstraction'), + 'BAR', + ); beforeEach(() => MockBuilder(TestWithoutDecoratorComponent).mock( InjectedAbstraction, @@ -154,11 +153,7 @@ describe('issue-455:abstract', () => { beforeEach(() => MockBuilder(TestWithoutDecoratorComponent).mock( InjectedAbstraction, - typeof jest === 'undefined' - ? jasmine - .createSpy('InjectedAbstraction') - .and.returnValue('BAR') - : jest.fn().mockReturnValue('BAR'), + mockReturnValue(createMock('InjectedAbstraction'), 'BAR'), { precise: true }, ), ); @@ -182,11 +177,7 @@ describe('issue-455:abstract', () => { MockBuilder(TestWithDecoratorComponent).provide({ provide: InjectedAbstraction, useFactory: () => - typeof jest === 'undefined' - ? jasmine - .createSpy('InjectedAbstraction') - .and.returnValue('QUX') - : jest.fn().mockReturnValue('QUX'), + mockReturnValue(createMock('InjectedAbstraction'), 'QUX'), }), ); diff --git a/tests/issue-455/token.spec.ts b/tests/issue-455/token.spec.ts index 3734db8763..7a6416e6f6 100644 --- a/tests/issue-455/token.spec.ts +++ b/tests/issue-455/token.spec.ts @@ -13,6 +13,8 @@ import { ngMocks, } from 'ng-mocks'; +import { mockReturnValue, createMock } from '../mock-helpers'; + interface InjectedAbstraction { (): string; hello: () => number; @@ -21,10 +23,8 @@ interface InjectedAbstraction { const TOKEN: InjectionToken = new (InjectionToken as any)('InjectedFn', { factory: () => { - const fn: any = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); - fn.hello = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const fn: any = createMock(); + fn.hello = createMock(); return fn; }, @@ -55,10 +55,7 @@ class TestWithDecoratorComponent { ngMocks.defaultMock( TOKEN, - () => - (typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('FOO') - : jest.fn().mockReturnValue('FOO')) as any, + () => mockReturnValue(createMock(), 'FOO') as any, ); // @see https://github.com/help-me-mom/ng-mocks/issues/455 @@ -107,12 +104,7 @@ describe('issue-455:token', () => { describe('without `precise` flag', () => { beforeEach(() => MockBuilder(TestWithoutDecoratorComponent) - .mock( - TOKEN, - (typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('BAR') - : jest.fn().mockReturnValue('BAR')) as any, - ) + .mock(TOKEN, mockReturnValue(createMock(), 'BAR') as any) .keep(NG_MOCKS_ROOT_PROVIDERS), ); @@ -132,9 +124,7 @@ describe('issue-455:token', () => { MockBuilder(TestWithoutDecoratorComponent) .mock( TOKEN as any, - (typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('BAR') - : jest.fn().mockReturnValue('BAR')) as any, + mockReturnValue(createMock(), 'BAR') as any, { precise: true }, ) .keep(NG_MOCKS_ROOT_PROVIDERS), @@ -158,10 +148,7 @@ describe('issue-455:token', () => { beforeEach(() => MockBuilder(TestWithDecoratorComponent).provide({ provide: TOKEN, - useFactory: () => - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('QUX') - : jest.fn().mockReturnValue('QUX'), + useFactory: () => mockReturnValue(createMock(), 'QUX'), }), ); diff --git a/tests/issue-488/test.spec.ts b/tests/issue-488/test.spec.ts index 5f0f233fc4..218190a9de 100644 --- a/tests/issue-488/test.spec.ts +++ b/tests/issue-488/test.spec.ts @@ -3,6 +3,8 @@ import { getTestBed, TestBed } from '@angular/core/testing'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Injectable() class TargetService { public method() { @@ -34,11 +36,7 @@ describe('issue-488', () => { describe('classic', () => { beforeEach(() => { service = ngMocks.findInstance(TargetService); - ngMocks.stubMember( - service, - 'method', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); + ngMocks.stubMember(service, 'method', createMock()); TestBed.createComponent(TargetComponent); }); @@ -53,11 +51,7 @@ describe('issue-488', () => { const testBed: any = getTestBed(); service = ngMocks.findInstance(TargetService); - ngMocks.stubMember( - service, - 'method', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); + ngMocks.stubMember(service, 'method', createMock()); if (testBed._instantiated || testBed._testModuleRef) { try { diff --git a/tests/issue-572/test.spec.ts b/tests/issue-572/test.spec.ts index fe7c8e9b92..7a0293ff34 100644 --- a/tests/issue-572/test.spec.ts +++ b/tests/issue-572/test.spec.ts @@ -2,6 +2,8 @@ import { Component, Injector } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-572', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -23,8 +25,7 @@ describe('issue-572', () => { beforeAll(() => (consoleWarn = console.warn)); beforeEach(() => { - console.warn = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + console.warn = createMock(); }); afterAll(() => { diff --git a/tests/issue-621/test.spec.ts b/tests/issue-621/test.spec.ts index e0ba3e3692..9e4ecbe012 100644 --- a/tests/issue-621/test.spec.ts +++ b/tests/issue-621/test.spec.ts @@ -23,18 +23,14 @@ class TargetComponent { // @see https://github.com/help-me-mom/ng-mocks/issues/621 describe('issue-621', () => { - ngMocks.faster(); + const factory = MockRenderFactory(TargetComponent, [ + 'update', + 'value', + ]); + ngMocks.faster(); beforeAll(() => MockBuilder(TargetComponent)); - - let factory: MockRenderFactory; - beforeAll( - () => - (factory = MockRenderFactory(TargetComponent, [ - 'update', - 'value', - ])), - ); + beforeAll(() => factory.configureTestBed()); it('does not proxy update inout', () => { const fixture = factory(); diff --git a/tests/issue-625/test.spec.ts b/tests/issue-625/test.spec.ts index ee7fde2df0..f6aec44823 100644 --- a/tests/issue-625/test.spec.ts +++ b/tests/issue-625/test.spec.ts @@ -12,6 +12,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + /* * As you can see, SomeService provided in forRoot() function. * I did so to reproduce the situation with NgxsModule and Store provider. @@ -87,11 +89,7 @@ describe('issue-625', () => { }); beforeEach(() => { - spy = MockInstance( - SomeService, - 'method', - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), - ); + spy = MockInstance(SomeService, 'method', createMock()); }); afterEach(() => MockInstance(SomeService)); diff --git a/tests/issue-735/test.spec.ts b/tests/issue-735/test.spec.ts index ab5535f017..dd1331e945 100644 --- a/tests/issue-735/test.spec.ts +++ b/tests/issue-735/test.spec.ts @@ -6,6 +6,8 @@ import { DomSanitizer } from '@angular/platform-browser'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-735', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -96,10 +98,7 @@ describe('issue-735', () => { afterAll(() => (console.log = consoleLog)); beforeEach(() => { - console.log = - typeof jest === 'undefined' - ? jasmine.createSpy() - : jest.fn(); + console.log = createMock(); }); beforeEach(() => MockBuilder(TargetComponent, TargetModule)); @@ -110,13 +109,9 @@ describe('issue-735', () => { ngMocks.stubMember( console, 'log', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(message => { - throw new Error(message); - }) - : jest.fn(message => { - throw new Error(message); - }), + createMock(message => { + throw new Error(message); + }), ); point.componentInstance.service.sanitize( SecurityContext.HTML, @@ -144,13 +139,9 @@ describe('issue-735', () => { ngMocks.stubMember( console, 'log', - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(message => { - throw new Error(message); - }) - : jest.fn(message => { - throw new Error(message); - }), + createMock(message => { + throw new Error(message); + }), ); point.componentInstance.service.sanitize( SecurityContext.HTML, diff --git a/tests/issue-736/test.spec.ts b/tests/issue-736/test.spec.ts index 9bda35f1a4..5f15746780 100644 --- a/tests/issue-736/test.spec.ts +++ b/tests/issue-736/test.spec.ts @@ -11,6 +11,8 @@ import { ngMocks, } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'modal', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -43,16 +45,9 @@ describe('issue-736', () => { .provide({ provide: ComponentFactoryResolver, useValue: { - resolveComponentFactory: - typeof jest === 'undefined' - ? jasmine.createSpy( - 'ComponentFactoryResolver.resolveComponentFactory', - ) - : jest - .fn() - .mockName( - 'ComponentFactoryResolver.resolveComponentFactory', - ), + resolveComponentFactory: createMock( + 'ComponentFactoryResolver.resolveComponentFactory', + ), }, }), ); diff --git a/tests/mock-helper-flush-test-bed/test.spec.ts b/tests/mock-helper-flush-test-bed/test.spec.ts index 122a1f3730..33f3786608 100644 --- a/tests/mock-helper-flush-test-bed/test.spec.ts +++ b/tests/mock-helper-flush-test-bed/test.spec.ts @@ -2,6 +2,8 @@ import { getTestBed } from '@angular/core/testing'; import { ngMocks } from 'ng-mocks'; +import { createMock, mockReturnValue } from '../mock-helpers'; + describe('mock-helper-flush-test-bed', () => { let originalShouldTearDownTestingModule: any; let originalTearDownTestingModule: any; @@ -23,15 +25,12 @@ describe('mock-helper-flush-test-bed', () => { it('should execute tearDownTestingModule', () => { const testBed: any = getTestBed(); - testBed.shouldTearDownTestingModule = - typeof jest === 'undefined' - ? jasmine.createSpy('spyShouldTearDown').and.returnValue(true) - : jest.fn().mockReturnValue(true); + testBed.shouldTearDownTestingModule = mockReturnValue( + createMock('spyShouldTearDown'), + true, + ); - testBed.tearDownTestingModule = - typeof jest === 'undefined' - ? jasmine.createSpy('spyTearDown') - : jest.fn(); + testBed.tearDownTestingModule = createMock('spyTearDown'); ngMocks.flushTestBed(); expect(testBed.tearDownTestingModule).toHaveBeenCalledTimes(1); @@ -40,17 +39,12 @@ describe('mock-helper-flush-test-bed', () => { it('should not execute tearDownTestingModule', () => { const testBed: any = getTestBed(); - testBed.shouldTearDownTestingModule = - typeof jest === 'undefined' - ? jasmine - .createSpy('spyShouldTearDown') - .and.returnValue(false) - : jest.fn().mockReturnValue(false); - - testBed.tearDownTestingModule = - typeof jest === 'undefined' - ? jasmine.createSpy('spyTearDown') - : jest.fn(); + testBed.shouldTearDownTestingModule = mockReturnValue( + createMock('spyShouldTearDown'), + false, + ); + + testBed.tearDownTestingModule = createMock('spyTearDown'); ngMocks.flushTestBed(); expect(testBed.tearDownTestingModule).not.toHaveBeenCalled(); diff --git a/tests/mock-helpers.ts b/tests/mock-helpers.ts new file mode 100644 index 0000000000..d4c817b938 --- /dev/null +++ b/tests/mock-helpers.ts @@ -0,0 +1,62 @@ +import { MockedFunction } from 'ng-mocks'; + +import funcGetVitest from './func.get-vitest'; +import funcHasVitest from './func.has-vitest'; + +export function createMock(): MockedFunction; +export function createMock(name: string): MockedFunction; +export function createMock(fakeImpl: (...args: any[]) => any): MockedFunction; +export function createMock(name: string, fakeImpl: (...args: any[]) => any): MockedFunction; +export function createMock(arg1?: string | ((...args: any[]) => any), arg2?: (...args: any[]) => any): MockedFunction { + const name = typeof arg1 === 'string' ? arg1 : 'mock.fn()'; + const fakeImpl = typeof arg1 === 'function' ? arg1 : arg2; + + return handleMockProcessor({ + jasmine: () => (fakeImpl ? jasmine.createSpy(name).and.callFake(fakeImpl) : jasmine.createSpy(name)), + jest: () => jest.fn(fakeImpl).mockName(name), + vitest: () => funcGetVitest().fn(fakeImpl).mockName(name), + }); +} + +export const mockReturnValue = (mock: MockedFunction, value: any): MockedFunction => + handleMockProcessor({ + jasmine: () => (mock as jasmine.Spy).and.returnValue(value), + jest: () => (mock as jest.Mock).mockReturnValue(value), + vitest: () => (mock as any).mockReturnValue(value), + }); + +export const mockThrowError = (mock: MockedFunction, error: Error | string): MockedFunction => + handleMockProcessor({ + jasmine: () => (mock as jasmine.Spy).and.throwError(typeof error === 'string' ? error : error.message), + jest: () => + (mock as jest.Mock).mockImplementation(() => { + throw error instanceof Error ? error : new Error(error); + }), + vitest: () => + (mock as any).mockImplementation(() => { + throw error instanceof Error ? error : new Error(error); + }), + }); + +export const clearMock = (mock: MockedFunction): void => + handleMockProcessor({ + jasmine: () => (mock as jasmine.Spy).calls.reset(), + jest: () => (mock as jest.Mock).mockClear(), + vitest: () => (mock as any).mockClear(), + }); + +export const handleMockProcessor = (handlers: { jasmine: () => any; jest: () => any; vitest: () => any }) => { + if (typeof jest !== 'undefined') { + return handlers.jest(); + } + + if (funcHasVitest()) { + return handlers.vitest(); + } + + if (typeof jasmine !== 'undefined') { + return handlers.jasmine(); + } + + throw new Error('No supported testing framework found'); +}; diff --git a/tests/mock-render-param-ref/test.spec.ts b/tests/mock-render-param-ref/test.spec.ts index 83f81583ee..210ee26b64 100644 --- a/tests/mock-render-param-ref/test.spec.ts +++ b/tests/mock-render-param-ref/test.spec.ts @@ -7,6 +7,8 @@ import { import { MockBuilder, MockRender } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-mock-render-param-ref', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -34,8 +36,7 @@ describe('mock-render-param-ref', () => { it('keeps refs w/ params', () => { const params = { input: 'v1', - output: - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(), + output: createMock(), }; // By default params are set to the render component. @@ -62,8 +63,7 @@ describe('mock-render-param-ref', () => { // Let's assert that spies have the same behavior. const currentSpy = params.output; - const newSpy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const newSpy = createMock(); params.output = newSpy; fixture.point.componentInstance.emit(); expect(currentSpy).not.toHaveBeenCalledWith('v3'); @@ -78,16 +78,14 @@ describe('mock-render-param-ref', () => { fixture.componentInstance, ); - const spyOutput = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spyOutput = createMock(); fixture.componentInstance.output.subscribe(spyOutput); fixture.componentInstance.input = 'v1'; fixture.detectChanges(); fixture.componentInstance.emit(); expect(spyOutput).toHaveBeenCalledWith('v1'); - const spyThis = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spyThis = createMock(); fixture.componentInstance.outputThis.subscribe(spyThis); fixture.componentInstance.emitThis(); expect(spyThis).toHaveBeenCalledWith( diff --git a/tests/ng-mocks-change/cdr-change.spec.ts b/tests/ng-mocks-change/cdr-change.spec.ts index c5365a03b1..302ef6735c 100644 --- a/tests/ng-mocks-change/cdr-change.spec.ts +++ b/tests/ng-mocks-change/cdr-change.spec.ts @@ -11,6 +11,8 @@ import { takeUntil } from 'rxjs/operators'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ providers: [ { @@ -89,10 +91,7 @@ describe('ng-mocks-change:cdr-change', () => { it('correctly changes CVA', () => { const fixture = MockRender(TargetComponent); const component = fixture.point.componentInstance; - const spy = - typeof jest === 'undefined' - ? jasmine.createSpy() - : jest.fn(); + const spy = createMock(); component.control.valueChanges .pipe(takeUntil(destroy$)) .subscribe(spy); @@ -158,8 +157,7 @@ describe('ng-mocks-change:cdr-change:full-mock', () => { it('correctly changes CVA', () => { const fixture = MockRender(TargetComponent); const component = fixture.point.componentInstance; - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); component.control.valueChanges .pipe(takeUntil(destroy$)) .subscribe(spy); diff --git a/tests/ng-mocks-change/cdr-input.spec.ts b/tests/ng-mocks-change/cdr-input.spec.ts index b08ae33742..d63f1cfc40 100644 --- a/tests/ng-mocks-change/cdr-input.spec.ts +++ b/tests/ng-mocks-change/cdr-input.spec.ts @@ -10,6 +10,8 @@ import { takeUntil } from 'rxjs/operators'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'cva-ng-mocks-change-cdr-input', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -89,10 +91,7 @@ describe('ng-mocks-change:cdr-input', () => { it('correctly changes CVA', () => { const fixture = MockRender(TargetComponent); const component = fixture.point.componentInstance; - const spy = - typeof jest === 'undefined' - ? jasmine.createSpy() - : jest.fn(); + const spy = createMock(); component.control.valueChanges .pipe(takeUntil(destroy$)) .subscribe(spy); @@ -158,8 +157,7 @@ describe('ng-mocks-change:cdr-change:full-mock', () => { it('correctly changes CVA', () => { const fixture = MockRender(TargetComponent); const component = fixture.point.componentInstance; - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); component.control.valueChanges .pipe(takeUntil(destroy$)) .subscribe(spy); diff --git a/tests/ng-mocks-click/317.spec.ts b/tests/ng-mocks-click/317.spec.ts index 89ac6a2e01..ef326f4c1c 100644 --- a/tests/ng-mocks-click/317.spec.ts +++ b/tests/ng-mocks-click/317.spec.ts @@ -2,6 +2,8 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-ng-mocks-click-317', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -15,8 +17,7 @@ describe('ng-mocks-click:317', () => { beforeEach(() => MockBuilder(TargetComponent)); it('finds by css selector', () => { - const update = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const update = createMock(); MockRender(TargetComponent, { update }); expect(update).not.toHaveBeenCalled(); ngMocks.click('a'); @@ -24,8 +25,7 @@ describe('ng-mocks-click:317', () => { }); it('finds by attribute selector', () => { - const update = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const update = createMock(); MockRender(TargetComponent, { update }); expect(update).not.toHaveBeenCalled(); ngMocks.click(['data-role', 'link']); diff --git a/tests/ng-mocks-crawl/test.spec.ts b/tests/ng-mocks-crawl/test.spec.ts index 4297e43c36..def7accdd4 100644 --- a/tests/ng-mocks-crawl/test.spec.ts +++ b/tests/ng-mocks-crawl/test.spec.ts @@ -1,5 +1,7 @@ import { MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + describe('ng-mocks-crawl', () => { it('finds all elements including ng-container', () => { const fixture = MockRender( @@ -106,8 +108,7 @@ describe('ng-mocks-crawl', () => { }); it('skips text nodes', () => { - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); // in case of jest // const spy = jest.fn(); const node: any = { @@ -126,8 +127,7 @@ describe('ng-mocks-crawl', () => { }); it('handles missing fixture', () => { - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); ngMocks.crawl('div', spy); ngMocks.crawl(['attr'], spy); expect(spy).not.toHaveBeenCalled(); diff --git a/tests/ng-mocks-output/317.spec.ts b/tests/ng-mocks-output/317.spec.ts index 806296f384..8a064ca3f1 100644 --- a/tests/ng-mocks-output/317.spec.ts +++ b/tests/ng-mocks-output/317.spec.ts @@ -2,6 +2,8 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-ng-mocks-output-317', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -15,8 +17,7 @@ describe('ng-mocks-output:317', () => { beforeEach(() => MockBuilder(TargetComponent)); it('finds by css selector', () => { - const spy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const spy = createMock(); MockRender( '
1
', { spy }, diff --git a/tests/ng-mocks-stub-member/test.spec.ts b/tests/ng-mocks-stub-member/test.spec.ts index 071e9f14a5..4161e45259 100644 --- a/tests/ng-mocks-stub-member/test.spec.ts +++ b/tests/ng-mocks-stub-member/test.spec.ts @@ -2,6 +2,12 @@ import { Injectable, NgModule } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { + createMock, + mockReturnValue, + mockThrowError, +} from '../mock-helpers'; + @Injectable() class TargetService { public readonly name = 'target'; @@ -38,12 +44,8 @@ describe('ng-mocks-stub-member', () => { expect(service.echo()).toEqual('mockEcho'); // checking getters and setters - const getSpy = - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('spy') - : jest.fn().mockReturnValue('spy'); - const setSpy = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const getSpy = mockReturnValue(createMock(), 'spy'); + const setSpy = createMock(); ngMocks.stubMember(service, 'name', getSpy, 'get'); ngMocks.stubMember(service, 'name', setSpy, 'set'); @@ -77,9 +79,7 @@ describe('ng-mocks-stub-member', () => { ngMocks.stubMember( service, 'echo', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('spy') - : jest.fn().mockReturnValue('spy'), + mockReturnValue(createMock(), 'spy'), ); expect(service.echo()).toEqual('spy'); @@ -88,9 +88,7 @@ describe('ng-mocks-stub-member', () => { ngMocks.stubMember( service, 'name', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('spy') - : jest.fn().mockReturnValue('spy'), + mockReturnValue(createMock(), 'spy'), 'get', ); expect(service.name).toEqual('spy'); @@ -99,11 +97,7 @@ describe('ng-mocks-stub-member', () => { ngMocks.stubMember( service, 'name', - typeof jest === 'undefined' - ? jasmine.createSpy().and.throwError('spy') - : jest.fn(() => { - throw new Error('spy'); - }), + mockThrowError(createMock(), 'spy'), 'set', ); try { @@ -118,9 +112,7 @@ describe('ng-mocks-stub-member', () => { ngMocks.stubMember( service, 'norm', - typeof jest === 'undefined' - ? jasmine.createSpy().and.returnValue('spy') - : jest.fn().mockReturnValue('spy'), + mockReturnValue(createMock(), 'spy'), 'get', ); expect(service.norm).toEqual('spy'); diff --git a/tests/ng-mocks-trigger/317.spec.ts b/tests/ng-mocks-trigger/317.spec.ts index 5f4527cb15..402207dba5 100644 --- a/tests/ng-mocks-trigger/317.spec.ts +++ b/tests/ng-mocks-trigger/317.spec.ts @@ -2,6 +2,8 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Component({ selector: 'target-ng-mocks-trigger-317', ['standalone' as never /* TODO: remove after upgrade to a14 */]: false, @@ -15,8 +17,7 @@ describe('ng-mocks-trigger:317', () => { beforeEach(() => MockBuilder(TargetComponent)); it('finds by css selector', () => { - const trigger = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + const trigger = createMock(); MockRender(TargetComponent, { trigger }); expect(trigger).not.toHaveBeenCalled(); ngMocks.trigger('input', 'focus'); diff --git a/tests/performance/test.spec.ts b/tests/performance/test.spec.ts index 9ec838437f..59384c0c8a 100644 --- a/tests/performance/test.spec.ts +++ b/tests/performance/test.spec.ts @@ -4,6 +4,8 @@ import { Component, Injectable, NgModule } from '@angular/core'; import { MockBuilder, ngMocks } from 'ng-mocks'; +import { createMock } from '../mock-helpers'; + @Injectable() class TargetService { public count = 0; @@ -36,10 +38,7 @@ describe('performance:correct', () => { beforeAll(() => { backupWarn = console.warn; - console.warn = - typeof jest === 'undefined' - ? jasmine.createSpy().and.callFake(console.log) - : jest.fn(console.log); + console.warn = createMock(console.log); }); afterAll(() => { @@ -67,8 +66,7 @@ describe('performance:wrong', () => { beforeAll(() => { backupWarn = console.warn; - console.warn = - typeof jest === 'undefined' ? jasmine.createSpy() : jest.fn(); + console.warn = createMock(); }); afterAll(() => { diff --git a/tests/spies/test.spec.ts b/tests/spies/test.spec.ts index b54f823618..5e7670050e 100644 --- a/tests/spies/test.spec.ts +++ b/tests/spies/test.spec.ts @@ -7,6 +7,8 @@ import { ngMocks, } from 'ng-mocks'; +import { mockReturnValue } from '../mock-helpers'; + @Injectable() class TargetService { protected value = 'TargetService'; @@ -54,13 +56,7 @@ describe('spies:real', () => { describe('spies:manual-mock', () => { beforeEach(() => { const spy = MockService(TargetService); - if (typeof jest !== 'undefined') { - ngMocks.stub(spy, 'echo').mockReturnValue('fake'); - } else if (typeof jasmine !== 'undefined') { - ngMocks.stub(spy, 'echo').and.returnValue('fake'); - } - // in case of jest - // ngMocks.stub(spy, 'echo').mockReturnValue('fake'); + mockReturnValue(ngMocks.stub(spy, 'echo'), 'fake'); (spy as any).manual = true; return MockBuilder(TargetComponent, TargetModule).mock( @@ -100,19 +96,10 @@ describe('spies:auto-mock', () => { expect(component).toBeDefined(); expect(targetService.echo).toHaveBeenCalledTimes(1); expect(targetService.echo).toHaveBeenCalledWith('constructor'); - if (typeof jest !== 'undefined') { - ngMocks - .stub(targetService, 'echo') - .mockReturnValue('faked'); - } else if (typeof jasmine !== 'undefined') { - ngMocks - .stub(targetService, 'echo') - .and.returnValue('faked'); - } - // in case of jest - // ngMocks - // .stub(targetService, 'echo') - // .mockReturnValue('faked'); + mockReturnValue( + ngMocks.stub(targetService, 'echo'), + 'faked', + ); expect(component.echo()).toEqual('faked'); expect(targetService.echo).toHaveBeenCalledTimes(2); }); diff --git a/tsconfig.json b/tsconfig.json index d5d40249ee..a16444f3e8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,8 @@ "karma-jasmine", "karma-junit-reporter", "karma-webpack", - "node" + "node", + "vitest/globals" ] }, "files": ["libs/ng-mocks/src/index.ts", "empty.ts", "test.ts", "karma.conf.ts"],