diff --git a/README.md b/README.md
index 0162167..0989a48 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# Angular Lib for OpenID Connect & OAuth2
+TODO
+
 [](https://www.npmjs.com/package/oidc-client-rx) [](https://www.npmjs.com/package/oidc-client-rx) [](https://www.npmjs.com/package/oidc-client-rx) [](https://github.com/prettier/prettier) [](https://coveralls.io/github/damienbod/oidc-client-rx?branch=main)
@@ -155,7 +157,7 @@ const token = this.oidcSecurityService.getAccessToken().subscribe(...);
And then you can use it in the HttpHeaders
```ts
-import { HttpHeaders } from '@angular/common/http';
+import { HttpHeaders } from '@ngify/http';
const token = this.oidcSecurityServices.getAccessToken().subscribe((token) => {
const httpOptions = {
diff --git a/biome.json b/biome.jsonc
similarity index 63%
rename from biome.json
rename to biome.jsonc
index 170a920..201671e 100644
--- a/biome.json
+++ b/biome.jsonc
@@ -18,8 +18,14 @@
}
},
"files": {
- "ignore": [
- ".vscode/*.json"
- ]
- }
+ "ignore": [".vscode/*.json"]
+ },
+ "overrides": [
+ {
+ "include": ["src/**/*.spec.ts", "src/test.ts", "test"],
+ "javascript": {
+ "globals": ["describe", "beforeEach", "it", "expect"]
+ }
+ }
+ ]
}
diff --git a/karma.conf.js b/karma.conf.js
deleted file mode 100644
index 6a1fb11..0000000
--- a/karma.conf.js
+++ /dev/null
@@ -1,50 +0,0 @@
-// Karma configuration file, see link for more information
-// https://karma-runner.github.io/1.0/config/configuration-file.html
-
-module.exports = function (config) {
- config.set({
- basePath: '',
- frameworks: ['jasmine', '@angular-devkit/build-angular'],
- plugins: [
- require('karma-jasmine'),
- require('karma-chrome-launcher'),
- require('karma-jasmine-html-reporter'),
- require('karma-coverage'),
- require('@angular-devkit/build-angular/plugins/karma'),
- ],
- client: {
- jasmine: {
- // you can add configuration options for Jasmine here
- // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
- // for example, you can disable the random execution with `random: false`
- // or set a specific seed with `seed: 4321`
- },
- clearContext: false, // leave Jasmine Spec Runner output visible in browser
- },
- jasmineHtmlReporter: {
- suppressAll: true, // removes the duplicated traces
- },
- coverageReporter: {
- dir: require('path').join(
- __dirname,
- '../../coverage/oidc-client-rx'
- ),
- subdir: '.',
- reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'lcov' }],
- },
- reporters: ['progress', 'kjhtml'],
- port: 9876,
- colors: true,
- logLevel: config.LOG_INFO,
- autoWatch: true,
- browsers: ['Chrome'],
- customLaunchers: {
- ChromeHeadlessNoSandbox: {
- base: 'ChromeHeadless',
- flags: ['--no-sandbox'],
- },
- },
- singleRun: false,
- restartOnFileChange: true,
- });
-};
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..f623415
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3006 @@
+{
+ "name": "oidc-client-rx",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "oidc-client-rx",
+ "version": "0.1.0",
+ "dependencies": {
+ "@ngify/http": "^2.0.4",
+ "injection-js": "git+https://github.com/mgechev/injection-js.git#81a10e0",
+ "rxjs": ">=7.4.0"
+ },
+ "devDependencies": {
+ "@evilmartians/lefthook": "^1.0.3",
+ "@playwright/test": "^1.49.1",
+ "@rslib/core": "^0.3.1",
+ "@types/node": "^22.10.1",
+ "@vitest/coverage-v8": "^3.0.1",
+ "rfc4648": "^1.5.0",
+ "typescript": "^5.7.3",
+ "ultracite": "^4.1.15",
+ "vitest": "^3.0.1"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.26.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz",
+ "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.26.7"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.26.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz",
+ "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
+ "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
+ "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
+ "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
+ "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
+ "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
+ "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
+ "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
+ "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
+ "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
+ "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
+ "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
+ "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
+ "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
+ "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
+ "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
+ "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
+ "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
+ "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
+ "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
+ "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
+ "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
+ "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@evilmartians/lefthook": {
+ "version": "1.10.10",
+ "resolved": "https://registry.npmjs.org/@evilmartians/lefthook/-/lefthook-1.10.10.tgz",
+ "integrity": "sha512-MRIA0zJzUBbmcbecI7QjI08li4ffpmZ6DeVydEiZSg0vSx5mElEMEjDEjkI60eSV0XOm7LRbQKz2rfW6NqH8Cw==",
+ "cpu": [
+ "x64",
+ "arm64",
+ "ia32"
+ ],
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "os": [
+ "darwin",
+ "linux",
+ "win32"
+ ],
+ "bin": {
+ "lefthook": "bin/index.js"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@module-federation/error-codes": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.8.4.tgz",
+ "integrity": "sha512-55LYmrDdKb4jt+qr8qE8U3al62ZANp3FhfVaNPOaAmdTh0jHdD8M3yf5HKFlr5xVkVO4eV/F/J2NCfpbh+pEXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@module-federation/runtime": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.8.4.tgz",
+ "integrity": "sha512-yZeZ7z2Rx4gv/0E97oLTF3V6N25vglmwXGgoeju/W2YjsFvWzVtCDI7zRRb0mJhU6+jmSM8jP1DeQGbea/AiZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@module-federation/error-codes": "0.8.4",
+ "@module-federation/sdk": "0.8.4"
+ }
+ },
+ "node_modules/@module-federation/runtime-tools": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.8.4.tgz",
+ "integrity": "sha512-fjVOsItJ1u5YY6E9FnS56UDwZgqEQUrWFnouRiPtK123LUuqUI9FH4redZoKWlE1PB0ir1Z3tnqy8eFYzPO38Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@module-federation/runtime": "0.8.4",
+ "@module-federation/webpack-bundler-runtime": "0.8.4"
+ }
+ },
+ "node_modules/@module-federation/sdk": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.8.4.tgz",
+ "integrity": "sha512-waABomIjg/5m1rPDBWYG4KUhS5r7OUUY7S+avpaVIY/tkPWB3ibRDKy2dNLLAMaLKq0u+B1qIdEp4NIWkqhqpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "isomorphic-rslog": "0.0.6"
+ }
+ },
+ "node_modules/@module-federation/webpack-bundler-runtime": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.8.4.tgz",
+ "integrity": "sha512-HggROJhvHPUX7uqBD/XlajGygMNM1DG0+4OAkk8MBQe4a18QzrRNzZt6XQbRTSG4OaEoyRWhQHvYD3Yps405tQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@module-federation/runtime": "0.8.4",
+ "@module-federation/sdk": "0.8.4"
+ }
+ },
+ "node_modules/@ngify/core": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@ngify/core/-/core-2.0.4.tgz",
+ "integrity": "sha512-MyZ6TrD4NEEEpy5yBoAtCyAXySpLvi6kBrvJk1vl9s4dkU5H+/bKBeAy5gPvdbLQ6c6NHD3Y4cnnMBbhdtVOnA==",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ }
+ },
+ "node_modules/@ngify/http": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@ngify/http/-/http-2.0.4.tgz",
+ "integrity": "sha512-3w3mMadsrkO0/xgLC5+79qqOJcRc+XvcBoOMZZBPFdiWg7wHWHULv48KHFVau+GbzvnXEza46W/xYyOMyR0F8g==",
+ "dependencies": {
+ "@ngify/core": "2.0.4",
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "rxjs": "^7.0.0"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@playwright/test": {
+ "version": "1.50.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.0.tgz",
+ "integrity": "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.50.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz",
+ "integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz",
+ "integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz",
+ "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz",
+ "integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz",
+ "integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz",
+ "integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz",
+ "integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz",
+ "integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz",
+ "integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz",
+ "integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz",
+ "integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz",
+ "integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz",
+ "integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz",
+ "integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz",
+ "integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz",
+ "integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz",
+ "integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz",
+ "integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz",
+ "integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rsbuild/core": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.2.3.tgz",
+ "integrity": "sha512-lUCt8gQe9E2PI3srcEJ1Na3GQYmsYuvAqK0f/k00HM0pEjrbOFC9Xq2kR85UoXHFqlTCIw/fLLDe91PKRCbKAw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@rspack/core": "1.2.2",
+ "@rspack/lite-tapable": "~1.0.1",
+ "@swc/helpers": "^0.5.15",
+ "core-js": "~3.40.0"
+ },
+ "bin": {
+ "rsbuild": "bin/rsbuild.js"
+ },
+ "engines": {
+ "node": ">=16.7.0"
+ }
+ },
+ "node_modules/@rslib/core": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@rslib/core/-/core-0.3.2.tgz",
+ "integrity": "sha512-BdR/1kjR+Jk614je0ijjEwGoY44fLtPg6PoWHoKfzMkqNMtFg40AwMaBS04SylvR4BuUt1Q+9k6NQ/IWdE5HWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rsbuild/core": "1.2.0-beta.1",
+ "rsbuild-plugin-dts": "0.3.2",
+ "tinyglobby": "^0.2.10"
+ },
+ "bin": {
+ "rslib": "bin/rslib.js"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "@microsoft/api-extractor": "^7",
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "@microsoft/api-extractor": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rslib/core/node_modules/@rsbuild/core": {
+ "version": "1.2.0-beta.1",
+ "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.2.0-beta.1.tgz",
+ "integrity": "sha512-+TzwALD2xEpgc2FQgjn1CtNtE2CTS1FELuWXpjI4AABjytYDGdaOHvHyCLXHiJpuvDdnyJumoN/T8i8zhbTkPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rspack/core": "1.2.0-beta.0",
+ "@rspack/lite-tapable": "~1.0.1",
+ "@swc/helpers": "^0.5.15",
+ "core-js": "~3.40.0"
+ },
+ "bin": {
+ "rsbuild": "bin/rsbuild.js"
+ },
+ "engines": {
+ "node": ">=16.7.0"
+ }
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.2.0-beta.0.tgz",
+ "integrity": "sha512-ZUBWVKCVC3uunZhjH7FAVLP83r/6QvPmYViA6n0JF3ycBmcJLkHJb26v42j6d5EfYfTtNvfRUlzHckIkFDQeDQ==",
+ "dev": true,
+ "license": "MIT",
+ "optionalDependencies": {
+ "@rspack/binding-darwin-arm64": "1.2.0-beta.0",
+ "@rspack/binding-darwin-x64": "1.2.0-beta.0",
+ "@rspack/binding-linux-arm64-gnu": "1.2.0-beta.0",
+ "@rspack/binding-linux-arm64-musl": "1.2.0-beta.0",
+ "@rspack/binding-linux-x64-gnu": "1.2.0-beta.0",
+ "@rspack/binding-linux-x64-musl": "1.2.0-beta.0",
+ "@rspack/binding-win32-arm64-msvc": "1.2.0-beta.0",
+ "@rspack/binding-win32-ia32-msvc": "1.2.0-beta.0",
+ "@rspack/binding-win32-x64-msvc": "1.2.0-beta.0"
+ }
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-darwin-arm64": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.0-beta.0.tgz",
+ "integrity": "sha512-g8NgY4OIjZf5LabAKOHNr2rs/WzVaxXpOSVsdHztQL6ETdeEpIPUul4p/5zivFNcrvJxVVeHzKJHyB5lqxDcTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-darwin-x64": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.0-beta.0.tgz",
+ "integrity": "sha512-+BH/1UpG96exJc6KhDOiSHAb05bUwxbYCd37HAJwcLxQgB7IEmPtBYvV5CtHysteM5NBtbNeeAcyXK+dIYvUew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-linux-arm64-gnu": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.0-beta.0.tgz",
+ "integrity": "sha512-LdIBNy5WAXJ1J9nB3bEyvqz7mJrMN/7cCtPHMmFBR1aTFbh1NAjYZl24fc+f59aSV5jAU9wfTrOtqtSwnXg4tQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-linux-arm64-musl": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.0-beta.0.tgz",
+ "integrity": "sha512-4tRi87UyEWV25X6Ul68kJJ/de/cwmASmrIUrCYmdWEdtWMN46UOz0OvxCYvcHTf0DCP8M1CZf0cSiRuG/hsxGA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-linux-x64-gnu": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.0-beta.0.tgz",
+ "integrity": "sha512-rWWrPwUH3V4yG46acZDIlqr7H/yCxbu+WdPhdIRBvgT7bisQkZa2HYx6MXmUXxx94U2iFy5bh+un0ho5FZOeCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-linux-x64-musl": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.0-beta.0.tgz",
+ "integrity": "sha512-9pgL17Bk8aSrTBx6VfQbb313RInDjlY9DfgV5ybbSsWaFs/oAs4oPy+kepWWixfb9Y2q/74bSBPrBNTBYQpknw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-win32-arm64-msvc": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.0-beta.0.tgz",
+ "integrity": "sha512-JQ06Q3uTclIk4AvKUqx0Royx2PqVcUuumEUFVWERbd01fntkQqI3RFrPazBYAIvk5JmXk40+CKA1CsFef4RKOA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-win32-ia32-msvc": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.0-beta.0.tgz",
+ "integrity": "sha512-rNz/sXjXLAqCZkDuTumqm9Aa47Hiu45+vkJ0XvbirJ0A+dzuyGjdtlinwLyZtCY+dVAlS+AcX5znJLlpTSnjjA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/binding-win32-x64-msvc": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.0-beta.0.tgz",
+ "integrity": "sha512-LKFcgaeEo7G6YLE5aKIbeWzXUpVZc02u0q4as0TjTTRBHd8r21GeaGJVh1Xm9YBkHpIX8Ho1DMftYVd+F6gHzw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rslib/core/node_modules/@rspack/core": {
+ "version": "1.2.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.2.0-beta.0.tgz",
+ "integrity": "sha512-0o0EYNeCwbRrh1l+P6HEKGS3Y+SVE/+J6SqDGGBsOixt/YzFeYNeaePWUnFfQ8a27jp9s//Ix6iuxMYGjWmitA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@module-federation/runtime-tools": "0.8.4",
+ "@rspack/binding": "1.2.0-beta.0",
+ "@rspack/lite-tapable": "1.0.1",
+ "caniuse-lite": "^1.0.30001616"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "@swc/helpers": ">=0.5.1"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rspack/binding": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.2.2.tgz",
+ "integrity": "sha512-GCZwpGFYlLTdJ2soPLwjw9z4LSZ+GdpbHNfBt3Cm/f/bAF8n6mZc7dHUqN893RFh7MPU17HNEL3fMw7XR+6pHg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "optionalDependencies": {
+ "@rspack/binding-darwin-arm64": "1.2.2",
+ "@rspack/binding-darwin-x64": "1.2.2",
+ "@rspack/binding-linux-arm64-gnu": "1.2.2",
+ "@rspack/binding-linux-arm64-musl": "1.2.2",
+ "@rspack/binding-linux-x64-gnu": "1.2.2",
+ "@rspack/binding-linux-x64-musl": "1.2.2",
+ "@rspack/binding-win32-arm64-msvc": "1.2.2",
+ "@rspack/binding-win32-ia32-msvc": "1.2.2",
+ "@rspack/binding-win32-x64-msvc": "1.2.2"
+ }
+ },
+ "node_modules/@rspack/binding-darwin-arm64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.2.tgz",
+ "integrity": "sha512-h23F8zEkXWhwMeScm0ZnN78Zh7hCDalxIWsm7bBS0eKadnlegUDwwCF8WE+8NjWr7bRzv0p3QBWlS5ufkcL4eA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-darwin-x64": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.2.tgz",
+ "integrity": "sha512-vG5s7FkEvwrGLfksyDRHwKAHUkhZt1zHZZXJQn4gZKjTBonje8ezdc7IFlDiWpC4S+oBYp73nDWkUzkGRbSdcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-linux-arm64-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.2.tgz",
+ "integrity": "sha512-VykY/kiYOzO8E1nYzfJ9+gQEHxb5B6lt5wa8M6xFi5B6jEGU+OsaGskmAZB9/GFImeFDHxDPvhUalI4R9p8O2Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-linux-arm64-musl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.2.tgz",
+ "integrity": "sha512-Z5vAC4wGfXi8XXZ6hs8Q06TYjr3zHf819HB4DI5i4C1eQTeKdZSyoFD0NHFG23bP4NWJffp8KhmoObcy9jBT5Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-linux-x64-gnu": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.2.tgz",
+ "integrity": "sha512-o3pDaL+cH5EeRbDE9gZcdZpBgp5iXvYZBBhe8vZQllYgI4zN5MJEuleV7WplG3UwTXlgZg3Kht4RORSOPn96vg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-linux-x64-musl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.2.tgz",
+ "integrity": "sha512-RE3e0xe4DdchHssttKzryDwjLkbrNk/4H59TkkWeGYJcLw41tmcOZVFQUOwKLUvXWVyif/vjvV/w1SMlqB4wQg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-win32-arm64-msvc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.2.tgz",
+ "integrity": "sha512-R+PKBYn6uzTaDdVqTHvjqiJPBr5ZHg1wg5UmFDLNH9OklzVFyQh1JInSdJRb7lzfzTRz6bEkkwUFBPQK/CGScw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-win32-ia32-msvc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.2.tgz",
+ "integrity": "sha512-dBqz3sRAGZ2f31FgzKLDvIRfq2haRP3X3XVCT0PsiMcvt7QJng+26aYYMy2THatd/nM8IwExYeitHWeiMBoruw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/binding-win32-x64-msvc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.2.tgz",
+ "integrity": "sha512-eeAvaN831KG553cMSHkVldyk6YQn4ujgRHov6r1wtREq7CD3/ka9LMkJUepCN85K7XtwYT0N4KpFIQyf5GTGoA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
+ "node_modules/@rspack/core": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.2.2.tgz",
+ "integrity": "sha512-EeHAmY65Uj62hSbUKesbrcWGE7jfUI887RD03G++Gj8jS4WPHEu1TFODXNOXg6pa7zyIvs2BK0Bm16Kwz8AEaQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@module-federation/runtime-tools": "0.8.4",
+ "@rspack/binding": "1.2.2",
+ "@rspack/lite-tapable": "1.0.1",
+ "caniuse-lite": "^1.0.30001616"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "@rspack/tracing": "^1.x",
+ "@swc/helpers": ">=0.5.1"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/tracing": {
+ "optional": true
+ },
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rspack/lite-tapable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz",
+ "integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.12.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz",
+ "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/@vitest/coverage-v8": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.4.tgz",
+ "integrity": "sha512-f0twgRCHgbs24Dp8cLWagzcObXMcuKtAwgxjJV/nnysPAJJk1JiKu/W0gIehZLmkljhJXU/E0/dmuQzsA/4jhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@bcoe/v8-coverage": "^1.0.2",
+ "debug": "^4.4.0",
+ "istanbul-lib-coverage": "^3.2.2",
+ "istanbul-lib-report": "^3.0.1",
+ "istanbul-lib-source-maps": "^5.0.6",
+ "istanbul-reports": "^3.1.7",
+ "magic-string": "^0.30.17",
+ "magicast": "^0.3.5",
+ "std-env": "^3.8.0",
+ "test-exclude": "^7.0.1",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@vitest/browser": "3.0.4",
+ "vitest": "3.0.4"
+ },
+ "peerDependenciesMeta": {
+ "@vitest/browser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.4.tgz",
+ "integrity": "sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.0.4",
+ "@vitest/utils": "3.0.4",
+ "chai": "^5.1.2",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.4.tgz",
+ "integrity": "sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.0.4",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.4.tgz",
+ "integrity": "sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.4.tgz",
+ "integrity": "sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "3.0.4",
+ "pathe": "^2.0.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.4.tgz",
+ "integrity": "sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.0.4",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.4.tgz",
+ "integrity": "sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^3.0.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.4.tgz",
+ "integrity": "sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.0.4",
+ "loupe": "^3.1.2",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "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/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001696",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz",
+ "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chai": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz",
+ "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "3.40.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
+ "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
+ "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esbuild": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
+ "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.24.2",
+ "@esbuild/android-arm": "0.24.2",
+ "@esbuild/android-arm64": "0.24.2",
+ "@esbuild/android-x64": "0.24.2",
+ "@esbuild/darwin-arm64": "0.24.2",
+ "@esbuild/darwin-x64": "0.24.2",
+ "@esbuild/freebsd-arm64": "0.24.2",
+ "@esbuild/freebsd-x64": "0.24.2",
+ "@esbuild/linux-arm": "0.24.2",
+ "@esbuild/linux-arm64": "0.24.2",
+ "@esbuild/linux-ia32": "0.24.2",
+ "@esbuild/linux-loong64": "0.24.2",
+ "@esbuild/linux-mips64el": "0.24.2",
+ "@esbuild/linux-ppc64": "0.24.2",
+ "@esbuild/linux-riscv64": "0.24.2",
+ "@esbuild/linux-s390x": "0.24.2",
+ "@esbuild/linux-x64": "0.24.2",
+ "@esbuild/netbsd-arm64": "0.24.2",
+ "@esbuild/netbsd-x64": "0.24.2",
+ "@esbuild/openbsd-arm64": "0.24.2",
+ "@esbuild/openbsd-x64": "0.24.2",
+ "@esbuild/sunos-x64": "0.24.2",
+ "@esbuild/win32-arm64": "0.24.2",
+ "@esbuild/win32-ia32": "0.24.2",
+ "@esbuild/win32-x64": "0.24.2"
+ }
+ },
+ "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/expect-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz",
+ "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
+ "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/injection-js": {
+ "version": "2.4.0",
+ "resolved": "git+ssh://git@github.com/mgechev/injection-js.git#81a10e03929a913486f5ccb88bb893c67beeb228",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8.5"
+ }
+ },
+ "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",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/isomorphic-rslog": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/isomorphic-rslog/-/isomorphic-rslog-0.0.6.tgz",
+ "integrity": "sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.17.6"
+ }
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.23",
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
+ "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
+ "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.25.4",
+ "@babel/types": "^7.25.4",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
+ "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/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/pathe": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz",
+ "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pathval": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+ "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/playwright": {
+ "version": "1.50.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.0.tgz",
+ "integrity": "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.50.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.50.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.0.tgz",
+ "integrity": "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
+ "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
+ "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.8",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rfc4648": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.4.tgz",
+ "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/rollup": {
+ "version": "4.32.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz",
+ "integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.6"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.32.1",
+ "@rollup/rollup-android-arm64": "4.32.1",
+ "@rollup/rollup-darwin-arm64": "4.32.1",
+ "@rollup/rollup-darwin-x64": "4.32.1",
+ "@rollup/rollup-freebsd-arm64": "4.32.1",
+ "@rollup/rollup-freebsd-x64": "4.32.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.32.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.32.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.32.1",
+ "@rollup/rollup-linux-arm64-musl": "4.32.1",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.32.1",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.32.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.32.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.32.1",
+ "@rollup/rollup-linux-x64-gnu": "4.32.1",
+ "@rollup/rollup-linux-x64-musl": "4.32.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.32.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.32.1",
+ "@rollup/rollup-win32-x64-msvc": "4.32.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rsbuild-plugin-dts": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/rsbuild-plugin-dts/-/rsbuild-plugin-dts-0.3.2.tgz",
+ "integrity": "sha512-Gjaf5ANA6R9t92Va6utNG1iyRxCE0QLoswKvR5UkOkX5GUpNyWveze+k/6L/qrkgqGRuJqUuYX3lrwatrOUZ3A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "magic-string": "^0.30.17",
+ "picocolors": "1.1.1",
+ "tinyglobby": "^0.2.10"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "@microsoft/api-extractor": "^7",
+ "@rsbuild/core": "1.x",
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "@microsoft/api-extractor": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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/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/std-env": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz",
+ "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "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/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "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/strip-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/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
+ "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^10.4.1",
+ "minimatch": "^9.0.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz",
+ "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.4.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/tinypool": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz",
+ "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
+ "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/typescript": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
+ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/ultracite": {
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/ultracite/-/ultracite-4.1.17.tgz",
+ "integrity": "sha512-CdugkIPgpaQle6Yzn4foEV4t+ocLmos2y/64hr+I9ZJ0XVDrO52AeTioc+n7wTxwUxuEF/VxBkcxXhyQYu9hzg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "commander": "^12.1.0"
+ },
+ "bin": {
+ "ultracite": "scripts/run.mjs"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vite": {
+ "version": "6.0.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
+ "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.24.2",
+ "postcss": "^8.4.49",
+ "rollup": "^4.23.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "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": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.4.tgz",
+ "integrity": "sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.4.0",
+ "es-module-lexer": "^1.6.0",
+ "pathe": "^2.0.2",
+ "vite": "^5.0.0 || ^6.0.0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite/node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/vitest": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.4.tgz",
+ "integrity": "sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "3.0.4",
+ "@vitest/mocker": "3.0.4",
+ "@vitest/pretty-format": "^3.0.4",
+ "@vitest/runner": "3.0.4",
+ "@vitest/snapshot": "3.0.4",
+ "@vitest/spy": "3.0.4",
+ "@vitest/utils": "3.0.4",
+ "chai": "^5.1.2",
+ "debug": "^4.4.0",
+ "expect-type": "^1.1.0",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.2",
+ "std-env": "^3.8.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.2",
+ "tinypool": "^1.0.2",
+ "tinyrainbow": "^2.0.0",
+ "vite": "^5.0.0 || ^6.0.0",
+ "vite-node": "3.0.4",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "3.0.4",
+ "@vitest/ui": "3.0.4",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/debug": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "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/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "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/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "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"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 69d57db..6fa083a 100644
--- a/package.json
+++ b/package.json
@@ -22,9 +22,7 @@
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
- "files": [
- "dist"
- ],
+ "files": ["dist"],
"scripts": {
"build": "rslib build",
"dev": "rslib build --watch",
@@ -39,19 +37,24 @@
"dependencies": {
"@ngify/http": "^2.0.4",
"injection-js": "git+https://github.com/mgechev/injection-js.git#81a10e0",
- "rxjs": ">=7.4.0"
+ "reflect-metadata": "^0.2.2"
+ },
+ "peerDependencies": {
+ "rxjs": "^7.4.0||>=8.0.0"
},
"devDependencies": {
"@evilmartians/lefthook": "^1.0.3",
"@playwright/test": "^1.49.1",
"@rslib/core": "^0.3.1",
- "@types/jasmine": "^4.0.0",
+ "@types/lodash-es": "^4.17.12",
"@types/node": "^22.10.1",
"@vitest/coverage-v8": "^3.0.1",
+ "lodash-es": "^4.17.21",
"rfc4648": "^1.5.0",
"typescript": "^5.7.3",
"ultracite": "^4.1.15",
- "vitest": "^3.0.1"
+ "vitest": "^3.0.1",
+ "rxjs": "^7.4.0"
},
"keywords": [
"rxjs",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 742ef71..003f594 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,9 +14,9 @@ importers:
injection-js:
specifier: git+https://github.com/mgechev/injection-js.git#81a10e0
version: https://codeload.github.com/mgechev/injection-js/tar.gz/81a10e0
- rxjs:
- specifier: '>=7.4.0'
- version: 7.8.1
+ reflect-metadata:
+ specifier: ^0.2.2
+ version: 0.2.2
devDependencies:
'@evilmartians/lefthook':
specifier: ^1.0.3
@@ -27,18 +27,24 @@ importers:
'@rslib/core':
specifier: ^0.3.1
version: 0.3.1(typescript@5.7.3)
- '@types/jasmine':
- specifier: ^4.0.0
- version: 4.6.4
+ '@types/lodash-es':
+ specifier: ^4.17.12
+ version: 4.17.12
'@types/node':
specifier: ^22.10.1
version: 22.10.7
'@vitest/coverage-v8':
specifier: ^3.0.1
version: 3.0.1(vitest@3.0.1(@types/node@22.10.7))
+ lodash-es:
+ specifier: ^4.17.21
+ version: 4.17.21
rfc4648:
specifier: ^1.5.0
version: 1.5.4
+ rxjs:
+ specifier: ^7.4.0
+ version: 7.8.1
typescript:
specifier: ^5.7.3
version: 5.7.3
@@ -469,8 +475,11 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
- '@types/jasmine@4.6.4':
- resolution: {integrity: sha512-qCw5sVW+ylTnrEhe5kfX4l6MgU9REXIVDa/lWEcvTOUmd+LqDYwyjovDq+Zk9blElaEHOj1URDQ/djEBVRf+pw==}
+ '@types/lodash-es@4.17.12':
+ resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
+ '@types/lodash@4.17.15':
+ resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==}
'@types/node@22.10.7':
resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==}
@@ -677,6 +686,9 @@ packages:
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+ lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+
loupe@3.1.2:
resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
@@ -748,6 +760,9 @@ packages:
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
engines: {node: ^10 || ^12 || >=14}
+ reflect-metadata@0.2.2:
+ resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
+
rfc4648@1.5.4:
resolution: {integrity: sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==}
@@ -1244,7 +1259,11 @@ snapshots:
'@types/estree@1.0.6': {}
- '@types/jasmine@4.6.4': {}
+ '@types/lodash-es@4.17.12':
+ dependencies:
+ '@types/lodash': 4.17.15
+
+ '@types/lodash@4.17.15': {}
'@types/node@22.10.7':
dependencies:
@@ -1469,6 +1488,8 @@ snapshots:
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
+ lodash-es@4.17.21: {}
+
loupe@3.1.2: {}
lru-cache@10.4.3: {}
@@ -1528,6 +1549,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ reflect-metadata@0.2.2: {}
+
rfc4648@1.5.4: {}
rollup@4.30.1:
diff --git a/src/api/data.service.spec.ts b/src/api/data.service.spec.ts
index ba33128..2061ae9 100644
--- a/src/api/data.service.spec.ts
+++ b/src/api/data.service.spec.ts
@@ -1,13 +1,15 @@
+import { TestBed } from '@/testing/testbed';
import {
HttpHeaders,
provideHttpClient,
withInterceptorsFromDi,
-} from '@angular/common/http';
+} from '@ngify/http';
import {
HttpTestingController,
provideHttpClientTesting,
-} from '@angular/common/http/testing';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+} from '@ngify/http/testing';
+import { lastValueFrom } from 'rxjs';
+import { vi } from 'vitest';
import { DataService } from './data.service';
import { HttpBaseService } from './http-base.service';
@@ -25,9 +27,6 @@ describe('Data Service', () => {
provideHttpClientTesting(),
],
});
- });
-
- beforeEach(() => {
dataService = TestBed.inject(DataService);
httpMock = TestBed.inject(HttpTestingController);
});
@@ -37,7 +36,7 @@ describe('Data Service', () => {
});
describe('get', () => {
- it('get call sets the accept header', waitForAsync(() => {
+ it('get call sets the accept header', async () => {
const url = 'testurl';
dataService
@@ -53,9 +52,9 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
- it('get call with token the accept header and the token', waitForAsync(() => {
+ it('get call with token the accept header and the token', async () => {
const url = 'testurl';
const token = 'token';
@@ -68,14 +67,14 @@ describe('Data Service', () => {
expect(req.request.method).toBe('GET');
expect(req.request.headers.get('Accept')).toBe('application/json');
- expect(req.request.headers.get('Authorization')).toBe('Bearer ' + token);
+ expect(req.request.headers.get('Authorization')).toBe(`Bearer ${token}`);
req.flush('bodyData');
httpMock.verify();
- }));
+ });
- it('call without ngsw-bypass param by default', waitForAsync(() => {
+ it('call without ngsw-bypass param by default', async () => {
const url = 'testurl';
dataService
@@ -92,9 +91,9 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
- it('call with ngsw-bypass param', waitForAsync(() => {
+ it('call with ngsw-bypass param', async () => {
const url = 'testurl';
dataService
@@ -102,7 +101,7 @@ describe('Data Service', () => {
.subscribe((data: unknown) => {
expect(data).toBe('bodyData');
});
- const req = httpMock.expectOne(url + '?ngsw-bypass=');
+ const req = httpMock.expectOne(`${url}?ngsw-bypass=`);
expect(req.request.method).toBe('GET');
expect(req.request.headers.get('Accept')).toBe('application/json');
@@ -111,11 +110,11 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
});
describe('post', () => {
- it('call sets the accept header when no other params given', waitForAsync(() => {
+ it('call sets the accept header when no other params given', async () => {
const url = 'testurl';
dataService
@@ -128,18 +127,23 @@ describe('Data Service', () => {
req.flush('bodyData');
- httpMock.verify();
- }));
+ await httpMock.verify();
+ });
- it('call sets custom headers ONLY (No ACCEPT header) when custom headers are given', waitForAsync(() => {
+ it('call sets custom headers ONLY (No ACCEPT header) when custom headers are given', async () => {
const url = 'testurl';
let headers = new HttpHeaders();
headers = headers.set('X-MyHeader', 'Genesis');
- dataService
- .post(url, { some: 'thing' }, { configId: 'configId1' }, headers)
- .subscribe();
+ await lastValueFrom(
+ dataService.post(
+ url,
+ { some: 'thing' },
+ { configId: 'configId1' },
+ headers
+ )
+ );
const req = httpMock.expectOne(url);
expect(req.request.method).toBe('POST');
@@ -149,14 +153,14 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
- it('call without ngsw-bypass param by default', waitForAsync(() => {
+ it('call without ngsw-bypass param by default', async () => {
const url = 'testurl';
- dataService
- .post(url, { some: 'thing' }, { configId: 'configId1' })
- .subscribe();
+ await lastValueFrom(
+ dataService.post(url, { some: 'thing' }, { configId: 'configId1' })
+ );
const req = httpMock.expectOne(url);
expect(req.request.method).toBe('POST');
@@ -166,18 +170,19 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
- it('call with ngsw-bypass param', waitForAsync(() => {
+ it('call with ngsw-bypass param', async () => {
const url = 'testurl';
- dataService
- .post(
+ await lastValueFrom(
+ dataService.post(
url,
{ some: 'thing' },
{ configId: 'configId1', ngswBypass: true }
)
- .subscribe();
+ );
+ // biome-ignore lint/style/useTemplate:
const req = httpMock.expectOne(url + '?ngsw-bypass=');
expect(req.request.method).toBe('POST');
@@ -187,6 +192,6 @@ describe('Data Service', () => {
req.flush('bodyData');
httpMock.verify();
- }));
+ });
});
});
diff --git a/src/auth-config.spec.ts b/src/auth-config.spec.ts
index c1e706d..5d8fe28 100644
--- a/src/auth-config.spec.ts
+++ b/src/auth-config.spec.ts
@@ -1,4 +1,4 @@
-import { PassedInitialConfig, createStaticLoader } from './auth-config';
+import { type PassedInitialConfig, createStaticLoader } from './auth-config';
describe('AuthConfig', () => {
describe('createStaticLoader', () => {
diff --git a/src/auth-config.ts b/src/auth-config.ts
index 9c785ec..6b441bc 100644
--- a/src/auth-config.ts
+++ b/src/auth-config.ts
@@ -1,9 +1,9 @@
-import { InjectionToken, Provider } from 'injection-js';
+import { InjectionToken, type Provider } from 'injection-js';
import {
- StsConfigLoader,
+ type StsConfigLoader,
StsConfigStaticLoader,
} from './config/loader/config-loader';
-import { OpenIdConfiguration } from './config/openid-configuration';
+import type { OpenIdConfiguration } from './config/openid-configuration';
export interface PassedInitialConfig {
config?: OpenIdConfiguration | OpenIdConfiguration[];
diff --git a/src/auth-state/auth-state.service.spec.ts b/src/auth-state/auth-state.service.spec.ts
index 7f1f239..5379e1e 100644
--- a/src/auth-state/auth-state.service.spec.ts
+++ b/src/auth-state/auth-state.service.spec.ts
@@ -1,13 +1,14 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
import { Observable } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
import { TokenValidationService } from '../validation/token-validation.service';
-import { ValidationResult } from '../validation/validation-result';
+import type { ValidationResult } from '../validation/validation-result';
import { AuthStateService } from './auth-state.service';
describe('Auth State Service', () => {
@@ -27,9 +28,6 @@ describe('Auth State Service', () => {
mockProvider(StoragePersistenceService),
],
});
- });
-
- beforeEach(() => {
authStateService = TestBed.inject(AuthStateService);
storagePersistenceService = TestBed.inject(StoragePersistenceService);
eventsService = TestBed.inject(PublicEventsService);
@@ -41,12 +39,12 @@ describe('Auth State Service', () => {
});
it('public authorize$ is observable$', () => {
- expect(authStateService.authenticated$).toEqual(jasmine.any(Observable));
+ expect(authStateService.authenticated$).toBeInstanceOf(Observable);
});
describe('setAuthorizedAndFireEvent', () => {
it('throws correct event with single config', () => {
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
@@ -55,7 +53,7 @@ describe('Auth State Service', () => {
{ configId: 'configId1' },
]);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: true,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: true },
@@ -64,7 +62,7 @@ describe('Auth State Service', () => {
});
it('throws correct event with multiple configs', () => {
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
@@ -74,7 +72,7 @@ describe('Auth State Service', () => {
{ configId: 'configId2' },
]);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: false },
@@ -86,26 +84,34 @@ describe('Auth State Service', () => {
it('throws correct event with multiple configs, one is authenticated', () => {
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
- spyOn(storagePersistenceService, 'getAccessToken')
- .withArgs(allConfigs[0])
- .and.returnValue('someAccessToken')
- .withArgs(allConfigs[1])
- .and.returnValue('');
+ mockImplementationWhenArgsEqual(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getAccessToken'),
+ [allConfigs[0]!],
+ () => 'someAccessToken'
+ ),
+ [allConfigs[1]!],
+ () => ''
+ );
- spyOn(storagePersistenceService, 'getIdToken')
- .withArgs(allConfigs[0])
- .and.returnValue('someIdToken')
- .withArgs(allConfigs[1])
- .and.returnValue('');
+ mockImplementationWhenArgsEqual(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getIdToken'),
+ [allConfigs[0]!],
+ () => 'someIdToken'
+ ),
+ [allConfigs[1]!],
+ () => ''
+ );
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
authStateService.setAuthenticatedAndFireEvent(allConfigs);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: true },
@@ -117,17 +123,20 @@ describe('Auth State Service', () => {
describe('setUnauthorizedAndFireEvent', () => {
it('persist AuthState In Storage', () => {
- const spy = spyOn(storagePersistenceService, 'resetAuthStateInStorage');
+ const spy = vi.spyOn(
+ storagePersistenceService,
+ 'resetAuthStateInStorage'
+ );
authStateService.setUnauthenticatedAndFireEvent(
{ configId: 'configId1' },
[{ configId: 'configId1' }]
);
- expect(spy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(spy).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
});
it('throws correct event with single config', () => {
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
@@ -137,7 +146,7 @@ describe('Auth State Service', () => {
[{ configId: 'configId1' }]
);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: false },
@@ -146,7 +155,7 @@ describe('Auth State Service', () => {
});
it('throws correct event with multiple configs', () => {
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
@@ -156,7 +165,7 @@ describe('Auth State Service', () => {
[{ configId: 'configId1' }, { configId: 'configId2' }]
);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: false },
@@ -166,19 +175,27 @@ describe('Auth State Service', () => {
});
it('throws correct event with multiple configs, one is authenticated', () => {
- spyOn(storagePersistenceService, 'getAccessToken')
- .withArgs({ configId: 'configId1' })
- .and.returnValue('someAccessToken')
- .withArgs({ configId: 'configId2' })
- .and.returnValue('');
+ mockImplementationWhenArgsEqual(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getAccessToken'),
+ [{ configId: 'configId1' }],
+ () => 'someAccessToken'
+ ),
+ [{ configId: 'configId2' }],
+ () => ''
+ );
- spyOn(storagePersistenceService, 'getIdToken')
- .withArgs({ configId: 'configId1' })
- .and.returnValue('someIdToken')
- .withArgs({ configId: 'configId2' })
- .and.returnValue('');
+ mockImplementationWhenArgsEqual(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getIdToken'),
+ [{ configId: 'configId1' }],
+ () => 'someIdToken'
+ ),
+ [{ configId: 'configId2' }],
+ () => ''
+ );
- const spy = spyOn(
+ const spy = vi.spyOn(
(authStateService as any).authenticatedInternal$,
'next'
);
@@ -188,7 +205,7 @@ describe('Auth State Service', () => {
[{ configId: 'configId1' }, { configId: 'configId2' }]
);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: 'configId1', isAuthenticated: true },
@@ -200,24 +217,27 @@ describe('Auth State Service', () => {
describe('updateAndPublishAuthState', () => {
it('calls eventsService', () => {
- spyOn(eventsService, 'fireEvent');
+ vi.spyOn(eventsService, 'fireEvent');
- authStateService.updateAndPublishAuthState({
+ const arg = {
isAuthenticated: false,
isRenewProcess: false,
validationResult: {} as ValidationResult,
- });
+ };
- expect(eventsService.fireEvent).toHaveBeenCalledOnceWith(
+ authStateService.updateAndPublishAuthState(arg);
+
+ expect(eventsService.fireEvent).toHaveBeenCalledOnce();
+ expect(eventsService.fireEvent).toHaveBeenCalledExactlyOnceWith(
EventTypes.NewAuthenticationResult,
- jasmine.any(Object)
+ arg
);
});
});
describe('setAuthorizationData', () => {
it('stores accessToken', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
const authResult = {
id_token: 'idtoken',
access_token: 'accesstoken',
@@ -237,18 +257,18 @@ describe('Auth State Service', () => {
[{ configId: 'configId1' }]
);
expect(spy).toHaveBeenCalledTimes(2);
- expect(spy.calls.allArgs()).toEqual([
+ expect(spy).toHaveBeenCalledWith([
['authzData', 'accesstoken', { configId: 'configId1' }],
[
'access_token_expires_at',
- jasmine.any(Number),
+ expect.any(Number),
{ configId: 'configId1' },
],
]);
});
it('does not crash and store accessToken when authResult is null', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
const authResult = null;
authStateService.setAuthorizationData(
@@ -262,7 +282,7 @@ describe('Auth State Service', () => {
});
it('calls setAuthenticatedAndFireEvent() method', () => {
- const spy = spyOn(authStateService, 'setAuthenticatedAndFireEvent');
+ const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent');
const authResult = {
id_token: 'idtoken',
access_token: 'accesstoken',
@@ -288,28 +308,29 @@ describe('Auth State Service', () => {
describe('getAccessToken', () => {
it('isAuthorized is false returns null', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
const result = authStateService.getAccessToken({ configId: 'configId1' });
expect(result).toBe('');
});
it('returns false if storagePersistenceService returns something falsy but authorized', () => {
- spyOn(authStateService, 'isAuthenticated').and.returnValue(true);
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
+ vi.spyOn(authStateService, 'isAuthenticated').mockReturnValue(true);
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
const result = authStateService.getAccessToken({ configId: 'configId1' });
expect(result).toBe('');
});
it('isAuthorized is true returns decodeURIComponent(token)', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
+
const result = authStateService.getAccessToken({ configId: 'configId1' });
expect(result).toBe(decodeURIComponent('HenloLegger'));
@@ -318,12 +339,14 @@ describe('Auth State Service', () => {
describe('getAuthenticationResult', () => {
it('isAuthorized is false returns null', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
- spyOn(storagePersistenceService, 'getAuthenticationResult')
- .withArgs({ configId: 'configId1' })
- .and.returnValue({});
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
+ [{ configId: 'configId1' }],
+ () => ({})
+ );
const result = authStateService.getAuthenticationResult({
configId: 'configId1',
@@ -333,10 +356,13 @@ describe('Auth State Service', () => {
});
it('returns false if storagePersistenceService returns something falsy but authorized', () => {
- spyOn(authStateService, 'isAuthenticated').and.returnValue(true);
- spyOn(storagePersistenceService, 'getAuthenticationResult')
- .withArgs({ configId: 'configId1' })
- .and.returnValue({});
+ vi.spyOn(authStateService, 'isAuthenticated').mockReturnValue(true);
+
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
+ [{ configId: 'configId1' }],
+ () => ({})
+ );
const result = authStateService.getAuthenticationResult({
configId: 'configId1',
@@ -346,15 +372,18 @@ describe('Auth State Service', () => {
});
it('isAuthorized is true returns object', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(storagePersistenceService, 'getAuthenticationResult')
- .withArgs({ configId: 'configId1' })
- .and.returnValue({ scope: 'HenloFuriend' });
+
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
+ [{ configId: 'configId1' }],
+ () => ({ scope: 'HenloFuriend' })
+ );
const result = authStateService.getAuthenticationResult({
configId: 'configId1',
@@ -366,18 +395,18 @@ describe('Auth State Service', () => {
describe('getIdToken', () => {
it('isAuthorized is false returns null', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
const result = authStateService.getIdToken({ configId: 'configId1' });
expect(result).toBe('');
});
it('isAuthorized is true returns decodeURIComponent(token)', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
const result = authStateService.getIdToken({ configId: 'configId1' });
@@ -388,8 +417,8 @@ describe('Auth State Service', () => {
describe('getRefreshToken', () => {
it('isAuthorized is false returns null', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
const result = authStateService.getRefreshToken({
configId: 'configId1',
});
@@ -398,13 +427,13 @@ describe('Auth State Service', () => {
});
it('isAuthorized is true returns decodeURIComponent(token)', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
'HenloRefreshLegger'
);
const result = authStateService.getRefreshToken({
@@ -417,105 +446,105 @@ describe('Auth State Service', () => {
describe('areAuthStorageTokensValid', () => {
it('isAuthorized is false returns false', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
const result = authStateService.areAuthStorageTokensValid({
configId: 'configId1',
});
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isAuthorized is true and id_token is expired returns true', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(
+ vi.spyOn(
authStateService as any,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authStateService as any,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = authStateService.areAuthStorageTokensValid({
configId: 'configId1',
});
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isAuthorized is true and access_token is expired returns true', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(
+ vi.spyOn(
authStateService as any,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
authStateService as any,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const result = authStateService.areAuthStorageTokensValid({
configId: 'configId1',
});
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isAuthorized is true and id_token is not expired returns true', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(
+ vi.spyOn(
authStateService as any,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
authStateService as any,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = authStateService.areAuthStorageTokensValid({
configId: 'configId1',
});
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('authState is AuthorizedState.Authorized and id_token is not expired fires event', () => {
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'HenloLegger'
);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'HenloFuriend'
);
- spyOn(
+ vi.spyOn(
authStateService as any,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
authStateService as any,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = authStateService.areAuthStorageTokensValid({
configId: 'configId1',
});
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
});
@@ -527,56 +556,65 @@ describe('Auth State Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(storagePersistenceService, 'getIdToken')
- .withArgs(config)
- .and.returnValue('idToken');
- const spy = spyOn(
- tokenValidationService,
- 'hasIdTokenExpired'
- ).and.callFake((_a, _b) => true);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'getIdToken'),
+ [config],
+ () => 'idToken'
+ );
+ const spy = vi
+ .spyOn(tokenValidationService, 'hasIdTokenExpired')
+ .mockImplementation((_a, _b) => true);
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
- expect(spy).toHaveBeenCalledOnceWith('idToken', config, 30);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('idToken', config, 30);
});
it('fires event if idToken is expired', () => {
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.callFake(
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockImplementation(
(_a, _b) => true
);
- const spy = spyOn(eventsService, 'fireEvent');
+ const spy = vi.spyOn(eventsService, 'fireEvent');
const config = {
configId: 'configId1',
renewTimeBeforeTokenExpiresInSeconds: 30,
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authnResult', config)
- .and.returnValue('idToken');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authnResult', config],
+ () => 'idToken'
+ );
const result =
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
expect(result).toBe(true);
- expect(spy).toHaveBeenCalledOnceWith(EventTypes.IdTokenExpired, true);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ EventTypes.IdTokenExpired,
+ true
+ );
});
it('does NOT fire event if idToken is NOT expired', () => {
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.callFake(
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockImplementation(
(_a, _b) => false
);
- const spy = spyOn(eventsService, 'fireEvent');
+ const spy = vi.spyOn(eventsService, 'fireEvent');
const config = {
configId: 'configId1',
renewTimeBeforeTokenExpiresInSeconds: 30,
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authnResult', config)
- .and.returnValue('idToken');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authnResult', config],
+ () => 'idToken'
+ );
+
const result =
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
@@ -595,41 +633,45 @@ describe('Auth State Service', () => {
renewTimeBeforeTokenExpiresInSeconds: 5,
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('access_token_expires_at', config)
- .and.returnValue(date);
- const spy = spyOn(
- tokenValidationService,
- 'validateAccessTokenNotExpired'
- ).and.returnValue(validateAccessTokenNotExpiredResult);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['access_token_expires_at', config],
+ () => date
+ );
+ const spy = vi
+ .spyOn(tokenValidationService, 'validateAccessTokenNotExpired')
+ .mockReturnValue(validateAccessTokenNotExpiredResult);
const result =
authStateService.hasAccessTokenExpiredIfExpiryExists(config);
- expect(spy).toHaveBeenCalledOnceWith(date, config, 5);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(date, config, 5);
expect(result).toEqual(expectedResult);
});
it('throws event when token is expired', () => {
const validateAccessTokenNotExpiredResult = false;
const expectedResult = !validateAccessTokenNotExpiredResult;
- // spyOn(configurationProvider, 'getOpenIDConfiguration').and.returnValue({ renewTimeBeforeTokenExpiresInSeconds: 5 });
+ // vi.spyOn(configurationProvider, 'getOpenIDConfiguration').mockReturnValue({ renewTimeBeforeTokenExpiresInSeconds: 5 });
const date = new Date(new Date().toUTCString());
const config = {
configId: 'configId1',
renewTimeBeforeTokenExpiresInSeconds: 5,
};
- spyOn(eventsService, 'fireEvent');
+ vi.spyOn(eventsService, 'fireEvent');
- spyOn(storagePersistenceService, 'read')
- .withArgs('access_token_expires_at', config)
- .and.returnValue(date);
- spyOn(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['access_token_expires_at', config],
+ () => date
+ );
+
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(validateAccessTokenNotExpiredResult);
+ ).mockReturnValue(validateAccessTokenNotExpiredResult);
authStateService.hasAccessTokenExpiredIfExpiryExists(config);
- expect(eventsService.fireEvent).toHaveBeenCalledOnceWith(
+ expect(eventsService.fireEvent).toHaveBeenCalledExactlyOnceWith(
EventTypes.TokenExpired,
expectedResult
);
diff --git a/src/auth-state/auth-state.service.ts b/src/auth-state/auth-state.service.ts
index 7c51a94..baf74a7 100644
--- a/src/auth-state/auth-state.service.ts
+++ b/src/auth-state/auth-state.service.ts
@@ -1,15 +1,15 @@
import { Injectable, inject } from 'injection-js';
-import { BehaviorSubject, Observable, throwError } from 'rxjs';
+import { BehaviorSubject, type Observable, throwError } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { AuthResult } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { AuthResult } from '../flows/callback-context';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
import { TokenValidationService } from '../validation/token-validation.service';
-import { AuthenticatedResult } from './auth-result';
-import { AuthStateResult } from './auth-state';
+import type { AuthenticatedResult } from './auth-result';
+import type { AuthStateResult } from './auth-state';
const DEFAULT_AUTHRESULT = {
isAuthenticated: false,
@@ -293,7 +293,7 @@ export class AuthStateService {
};
}
- return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
+ return this.checkallConfigsIfTheyAreAuthenticated(allConfigs);
}
private composeUnAuthenticatedResult(
@@ -310,10 +310,10 @@ export class AuthStateService {
};
}
- return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
+ return this.checkallConfigsIfTheyAreAuthenticated(allConfigs);
}
- private checkAllConfigsIfTheyAreAuthenticated(
+ private checkallConfigsIfTheyAreAuthenticated(
allConfigs: OpenIdConfiguration[]
): AuthenticatedResult {
const allConfigsAuthenticated = allConfigs.map((config) => ({
diff --git a/src/auth-state/check-auth.service.spec.ts b/src/auth-state/check-auth.service.spec.ts
index d7f9534..5f491b7 100644
--- a/src/auth-state/check-auth.service.spec.ts
+++ b/src/auth-state/check-auth.service.spec.ts
@@ -1,7 +1,10 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
+import {
+ TestBed,
+ mockImplementationWhenArgsEqual,
+ mockRouterProvider,
+} from '@/testing';
import { of, throwError } from 'rxjs';
-import { mockAbstractProvider, mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { AutoLoginService } from '../auto-login/auto-login.service';
import { CallbackService } from '../callback/callback.service';
import { PeriodicallyTokenCheckService } from '../callback/periodically-token-check.service';
@@ -10,16 +13,17 @@ import {
StsConfigLoader,
StsConfigStaticLoader,
} from '../config/loader/config-loader';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { CheckSessionService } from '../iframe/check-session.service';
import { SilentRenewService } from '../iframe/silent-renew.service';
import { LoggerService } from '../logging/logger.service';
-import { LoginResponse } from '../login/login-response';
+import type { LoginResponse } from '../login/login-response';
import { PopUpService } from '../login/popup/popup.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockAbstractProvider, mockProvider } from '../testing/mock';
import { UserService } from '../user-data/user.service';
import { CurrentUrlService } from '../utils/url/current-url.service';
import { AuthStateService } from './auth-state.service';
@@ -42,8 +46,9 @@ describe('CheckAuthService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule],
+ imports: [],
providers: [
+ mockRouterProvider(),
mockProvider(CheckSessionService),
mockProvider(SilentRenewService),
mockProvider(UserService),
@@ -60,9 +65,6 @@ describe('CheckAuthService', () => {
mockProvider(StoragePersistenceService),
],
});
- });
-
- beforeEach(() => {
checkAuthService = TestBed.inject(CheckAuthService);
refreshSessionService = TestBed.inject(RefreshSessionService);
userService = TestBed.inject(UserService);
@@ -80,6 +82,7 @@ describe('CheckAuthService', () => {
publicEventsService = TestBed.inject(PublicEventsService);
});
+ // biome-ignore lint/correctness/noUndeclaredVariables:
afterEach(() => {
storagePersistenceService.clear({} as OpenIdConfiguration);
});
@@ -89,97 +92,95 @@ describe('CheckAuthService', () => {
});
describe('checkAuth', () => {
- it('uses config with matching state when url has state param and config with state param is stored', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- 'the-state-param'
- );
+ it('uses config with matching state when url has state param and config with state param is stored', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue('the-state-param');
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(storagePersistenceService, 'read')
- .withArgs('authStateControl', allConfigs[0])
- .and.returnValue('the-state-param');
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authStateControl', allConfigs[0]!],
+ () => 'the-state-param'
+ );
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
- allConfigs[0],
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ allConfigs[0]!,
allConfigs,
undefined
);
});
- }));
+ });
- it('throws error when url has state param and stored config with matching state param is not found', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- 'the-state-param'
- );
+ it('throws error when url has state param and stored config with matching state param is not found', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue('the-state-param');
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(storagePersistenceService, 'read')
- .withArgs('authStateControl', allConfigs[0])
- .and.returnValue('not-matching-state-param');
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authStateControl', allConfigs[0]!],
+ () => 'not-matching-state-param'
+ );
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe({
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe({
error: (err) => {
expect(err).toBeTruthy();
expect(spy).not.toHaveBeenCalled();
},
});
- }));
+ });
- it('uses first/default config when no param is passed', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- null
- );
+ it('uses first/default config when no param is passed', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue(null);
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1', authority: 'some-authority' },
allConfigs,
undefined
);
});
- }));
+ });
- it('returns null and sendMessageToMainWindow if currently in a popup', waitForAsync(() => {
+ it('returns null and sendMessageToMainWindow if currently in a popup', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
+ vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
true
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOnProperty(popUpService as any, 'windowInternal').and.returnValue({
+ vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window,
});
- spyOn(storagePersistenceService, 'read').and.returnValue(null);
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);
- spyOn(popUpService, 'isCurrentlyInPopup').and.returnValue(true);
- const popupSpy = spyOn(popUpService, 'sendMessageToMainWindow');
+ vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
+ const popupSpy = vi.spyOn(popUpService, 'sendMessageToMainWindow');
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -191,29 +192,28 @@ describe('CheckAuthService', () => {
});
expect(popupSpy).toHaveBeenCalled();
});
- }));
+ });
- it('returns isAuthenticated: false with error message in case handleCallbackAndFireEvents throws an error', waitForAsync(() => {
+ it('returns isAuthenticated: false with error message in case handleCallbackAndFireEvents throws an error', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(true);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(true);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const spy = spyOn(
- callBackService,
- 'handleCallbackAndFireEvents'
- ).and.returnValue(throwError(() => new Error('ERROR')));
+ const spy = vi
+ .spyOn(callBackService, 'handleCallbackAndFireEvents')
+ .mockReturnValue(throwError(() => new Error('ERROR')));
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -225,30 +225,29 @@ describe('CheckAuthService', () => {
});
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('calls callbackService.handlePossibleStsCallback with current url when callback is true', waitForAsync(() => {
+ it('calls callbackService.handlePossibleStsCallback with current url when callback is true', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(true);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(true);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'getAccessToken').and.returnValue('at');
- spyOn(authStateService, 'getIdToken').and.returnValue('idt');
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
- const spy = spyOn(
- callBackService,
- 'handleCallbackAndFireEvents'
- ).and.returnValue(of({} as CallbackContext));
+ const spy = vi
+ .spyOn(callBackService, 'handleCallbackAndFireEvents')
+ .mockReturnValue(of({} as CallbackContext));
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: true,
@@ -259,31 +258,30 @@ describe('CheckAuthService', () => {
});
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('does NOT call handleCallbackAndFireEvents with current url when callback is false', waitForAsync(() => {
+ it('does NOT call handleCallbackAndFireEvents with current url when callback is false', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const spy = spyOn(
- callBackService,
- 'handleCallbackAndFireEvents'
- ).and.returnValue(of({} as CallbackContext));
+ const spy = vi
+ .spyOn(callBackService, 'handleCallbackAndFireEvents')
+ .mockReturnValue(of({} as CallbackContext));
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'getAccessToken').and.returnValue('at');
- spyOn(authStateService, 'getIdToken').and.returnValue('idt');
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: true,
@@ -294,37 +292,37 @@ describe('CheckAuthService', () => {
});
expect(spy).not.toHaveBeenCalled();
});
- }));
+ });
- it('does fire the auth and user data events when it is not a callback from the security token service and is authenticated', waitForAsync(() => {
+ it('does fire the auth and user data events when it is not a callback from the security token service and is authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(userService, 'getUserDataFromStore').and.returnValue({
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue({
some: 'user-data',
});
- spyOn(authStateService, 'getAccessToken').and.returnValue('at');
- spyOn(authStateService, 'getIdToken').and.returnValue('idt');
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
- const setAuthorizedAndFireEventSpy = spyOn(
+ const setAuthorizedAndFireEventSpy = vi.spyOn(
authStateService,
'setAuthenticatedAndFireEvent'
);
- const userServiceSpy = spyOn(userService, 'publishUserDataIfExists');
+ const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: true,
@@ -338,34 +336,34 @@ describe('CheckAuthService', () => {
expect(setAuthorizedAndFireEventSpy).toHaveBeenCalled();
expect(userServiceSpy).toHaveBeenCalled();
});
- }));
+ });
- it('does NOT fire the auth and user data events when it is not a callback from the security token service and is NOT authenticated', waitForAsync(() => {
+ it('does NOT fire the auth and user data events when it is not a callback from the security token service and is NOT authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOn(authStateService, 'getAccessToken').and.returnValue('at');
- spyOn(authStateService, 'getIdToken').and.returnValue('it');
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('it');
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- const setAuthorizedAndFireEventSpy = spyOn(
+ const setAuthorizedAndFireEventSpy = vi.spyOn(
authStateService,
'setAuthenticatedAndFireEvent'
);
- const userServiceSpy = spyOn(userService, 'publishUserDataIfExists');
+ const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -377,27 +375,27 @@ describe('CheckAuthService', () => {
expect(setAuthorizedAndFireEventSpy).not.toHaveBeenCalled();
expect(userServiceSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('if authenticated return true', waitForAsync(() => {
+ it('if authenticated return true', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'getAccessToken').and.returnValue('at');
- spyOn(authStateService, 'getIdToken').and.returnValue('idt');
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
checkAuthService
- .checkAuth(allConfigs[0], allConfigs)
+ .checkAuth(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: true,
@@ -407,273 +405,279 @@ describe('CheckAuthService', () => {
idToken: 'idt',
});
});
- }));
+ });
- it('if authenticated set auth and fires event ', waitForAsync(() => {
+ it('if authenticated set auth and fires event ', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const spy = spyOn(authStateService, 'setAuthenticatedAndFireEvent');
+ const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('if authenticated publishUserdataIfExists', waitForAsync(() => {
+ it('if authenticated publishUserdataIfExists', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const spy = spyOn(userService, 'publishUserDataIfExists');
+ const spy = vi.spyOn(userService, 'publishUserDataIfExists');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('if authenticated callbackService startTokenValidationPeriodically', waitForAsync(() => {
+ it('if authenticated callbackService startTokenValidationPeriodically', async () => {
const config = {
authority: 'authority',
tokenRefreshInSeconds: 7,
};
const allConfigs = [config];
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- const spy = spyOn(
+ const spy = vi.spyOn(
periodicallyTokenCheckService,
'startTokenValidationPeriodically'
);
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('if isCheckSessionConfigured call checkSessionService.start()', waitForAsync(() => {
+ it('if isCheckSessionConfigured call checkSessionService.start()', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(checkSessionService, 'isCheckSessionConfigured').and.returnValue(
+ vi.spyOn(checkSessionService, 'isCheckSessionConfigured').mockReturnValue(
true
);
- const spy = spyOn(checkSessionService, 'start');
+ const spy = vi.spyOn(checkSessionService, 'start');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('if isSilentRenewConfigured call getOrCreateIframe()', waitForAsync(() => {
+ it('if isSilentRenewConfigured call getOrCreateIframe()', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(silentRenewService, 'isSilentRenewConfigured').and.returnValue(
+ vi.spyOn(silentRenewService, 'isSilentRenewConfigured').mockReturnValue(
true
);
- const spy = spyOn(silentRenewService, 'getOrCreateIframe');
+ const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('calls checkSavedRedirectRouteAndNavigate if authenticated', waitForAsync(() => {
+ it('calls checkSavedRedirectRouteAndNavigate if authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const spy = spyOn(autoLoginService, 'checkSavedRedirectRouteAndNavigate');
+ const spy = vi.spyOn(
+ autoLoginService,
+ 'checkSavedRedirectRouteAndNavigate'
+ );
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalledTimes(1);
- expect(spy).toHaveBeenCalledOnceWith(allConfigs[0]);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
});
- }));
+ });
- it('does not call checkSavedRedirectRouteAndNavigate if not authenticated', waitForAsync(() => {
+ it('does not call checkSavedRedirectRouteAndNavigate if not authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const spy = spyOn(autoLoginService, 'checkSavedRedirectRouteAndNavigate');
+ const spy = vi.spyOn(
+ autoLoginService,
+ 'checkSavedRedirectRouteAndNavigate'
+ );
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
expect(spy).toHaveBeenCalledTimes(0);
});
- }));
+ });
- it('fires CheckingAuth-Event on start and finished event on end', waitForAsync(() => {
+ it('fires CheckingAuth-Event on start and finished event on end', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const fireEventSpy = spyOn(publicEventsService, 'fireEvent');
+ const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
- expect(fireEventSpy.calls.allArgs()).toEqual([
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
+ expect(fireEventSpy).toHaveBeenCalledWith([
[EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinished],
]);
});
- }));
+ });
- it('fires CheckingAuth-Event on start and CheckingAuthFinishedWithError event on end if exception occurs', waitForAsync(() => {
+ it('fires CheckingAuth-Event on start and CheckingAuthFinishedWithError event on end if exception occurs', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- const fireEventSpy = spyOn(publicEventsService, 'fireEvent');
+ const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
- spyOn(callBackService, 'isCallback').and.returnValue(true);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(true);
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
throwError(() => new Error('ERROR'))
);
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
- expect(fireEventSpy.calls.allArgs()).toEqual([
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
+ expect(fireEventSpy).toHaveBeenCalledWith([
[EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinishedWithError, 'ERROR'],
]);
});
- }));
+ });
- it('fires CheckingAuth-Event on start and finished event on end if not authenticated', waitForAsync(() => {
+ it('fires CheckingAuth-Event on start and finished event on end if not authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(currentUrlService, 'getCurrentUrl').and.returnValue(
+ vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200'
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const fireEventSpy = spyOn(publicEventsService, 'fireEvent');
+ const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
- checkAuthService.checkAuth(allConfigs[0], allConfigs).subscribe(() => {
- expect(fireEventSpy.calls.allArgs()).toEqual([
+ checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => {
+ expect(fireEventSpy).toBeCalledWith([
[EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinished],
]);
});
- }));
+ });
});
describe('checkAuthIncludingServer', () => {
- it('if isSilentRenewConfigured call getOrCreateIframe()', waitForAsync(() => {
+ it('if isSilentRenewConfigured call getOrCreateIframe()', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({ isAuthenticated: true } as LoginResponse)
);
- spyOn(silentRenewService, 'isSilentRenewConfigured').and.returnValue(
+ vi.spyOn(silentRenewService, 'isSilentRenewConfigured').mockReturnValue(
true
);
- const spy = spyOn(silentRenewService, 'getOrCreateIframe');
+ const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
checkAuthService
- .checkAuthIncludingServer(allConfigs[0], allConfigs)
+ .checkAuthIncludingServer(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('does forceRefreshSession get called and is NOT authenticated', waitForAsync(() => {
+ it('does forceRefreshSession get called and is NOT authenticated', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({
idToken: 'idToken',
accessToken: 'access_token',
@@ -684,42 +688,45 @@ describe('CheckAuthService', () => {
);
checkAuthService
- .checkAuthIncludingServer(allConfigs[0], allConfigs)
+ .checkAuthIncludingServer(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toBeTruthy();
});
- }));
+ });
- it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing with silentrenew', waitForAsync(() => {
+ it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing with silentrenew', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(checkSessionService, 'isCheckSessionConfigured').and.returnValue(
+ vi.spyOn(checkSessionService, 'isCheckSessionConfigured').mockReturnValue(
true
);
- spyOn(silentRenewService, 'isSilentRenewConfigured').and.returnValue(
+ vi.spyOn(silentRenewService, 'isSilentRenewConfigured').mockReturnValue(
true
);
- const checkSessionServiceStartSpy = spyOn(checkSessionService, 'start');
- const periodicallyTokenCheckServiceSpy = spyOn(
+ const checkSessionServiceStartSpy = vi.spyOn(
+ checkSessionService,
+ 'start'
+ );
+ const periodicallyTokenCheckServiceSpy = vi.spyOn(
periodicallyTokenCheckService,
'startTokenValidationPeriodically'
);
- const getOrCreateIframeSpy = spyOn(
+ const getOrCreateIframeSpy = vi.spyOn(
silentRenewService,
'getOrCreateIframe'
);
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({
idToken: 'idToken',
accessToken: 'access_token',
@@ -730,46 +737,51 @@ describe('CheckAuthService', () => {
);
checkAuthService
- .checkAuthIncludingServer(allConfigs[0], allConfigs)
+ .checkAuthIncludingServer(allConfigs[0]!, allConfigs)
.subscribe(() => {
- expect(checkSessionServiceStartSpy).toHaveBeenCalledOnceWith(
+ expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
allConfigs[0]
);
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);
- expect(getOrCreateIframeSpy).toHaveBeenCalledOnceWith(allConfigs[0]);
+ expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith(
+ allConfigs[0]
+ );
});
- }));
+ });
- it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing without silentrenew', waitForAsync(() => {
+ it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing without silentrenew', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority' },
];
- spyOn(callBackService, 'isCallback').and.returnValue(false);
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(callBackService, 'isCallback').mockReturnValue(false);
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOn(callBackService, 'handleCallbackAndFireEvents').and.returnValue(
+ vi.spyOn(callBackService, 'handleCallbackAndFireEvents').mockReturnValue(
of({} as CallbackContext)
);
- spyOn(checkSessionService, 'isCheckSessionConfigured').and.returnValue(
+ vi.spyOn(checkSessionService, 'isCheckSessionConfigured').mockReturnValue(
true
);
- spyOn(silentRenewService, 'isSilentRenewConfigured').and.returnValue(
+ vi.spyOn(silentRenewService, 'isSilentRenewConfigured').mockReturnValue(
false
);
- const checkSessionServiceStartSpy = spyOn(checkSessionService, 'start');
- const periodicallyTokenCheckServiceSpy = spyOn(
+ const checkSessionServiceStartSpy = vi.spyOn(
+ checkSessionService,
+ 'start'
+ );
+ const periodicallyTokenCheckServiceSpy = vi.spyOn(
periodicallyTokenCheckService,
'startTokenValidationPeriodically'
);
- const getOrCreateIframeSpy = spyOn(
+ const getOrCreateIframeSpy = vi.spyOn(
silentRenewService,
'getOrCreateIframe'
);
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({
idToken: 'idToken',
accessToken: 'access_token',
@@ -780,69 +792,67 @@ describe('CheckAuthService', () => {
);
checkAuthService
- .checkAuthIncludingServer(allConfigs[0], allConfigs)
+ .checkAuthIncludingServer(allConfigs[0]!, allConfigs)
.subscribe(() => {
- expect(checkSessionServiceStartSpy).toHaveBeenCalledOnceWith(
+ expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
allConfigs[0]
);
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);
expect(getOrCreateIframeSpy).not.toHaveBeenCalled();
});
- }));
+ });
});
describe('checkAuthMultiple', () => {
- it('uses config with matching state when url has state param and config with state param is stored', waitForAsync(() => {
+ it('uses config with matching state when url has state param and config with state param is stored', async () => {
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority1' },
{ configId: 'configId2', authority: 'some-authority2' },
];
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- 'the-state-param'
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue('the-state-param');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authStateControl', allConfigs[0]!],
+ () => 'the-state-param'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authStateControl', allConfigs[0])
- .and.returnValue('the-state-param');
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => {
expect(Array.isArray(result)).toBe(true);
expect(spy).toHaveBeenCalledTimes(2);
- expect(spy.calls.argsFor(0)).toEqual([
- allConfigs[0],
+ expect(vi.mocked(spy).mock.calls[0]).toEqual([
+ allConfigs[0]!,
allConfigs,
undefined,
]);
- expect(spy.calls.argsFor(1)).toEqual([
+ expect(vi.mocked(spy).mock.calls[1]).toEqual([
allConfigs[1],
allConfigs,
undefined,
]);
});
- }));
+ });
- it('uses config from passed configId if configId was passed and returns all results', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- null
- );
+ it('uses config from passed configId if configId was passed and returns all results', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue(null);
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority1' },
{ configId: 'configId2', authority: 'some-authority2' },
];
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => {
expect(Array.isArray(result)).toBe(true);
- expect(spy.calls.allArgs()).toEqual([
+ expect(spy).toBeCalledWith([
[
{ configId: 'configId1', authority: 'some-authority1' },
allConfigs,
@@ -855,43 +865,42 @@ describe('CheckAuthService', () => {
],
]);
});
- }));
+ });
- it('runs through all configs if no parameter is passed and has no state in url', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- null
- );
+ it('runs through all configs if no parameter is passed and has no state in url', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue(null);
const allConfigs = [
{ configId: 'configId1', authority: 'some-authority1' },
{ configId: 'configId2', authority: 'some-authority2' },
];
- const spy = spyOn(
- checkAuthService as any,
- 'checkAuthWithConfig'
- ).and.callThrough();
+ const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => {
expect(Array.isArray(result)).toBe(true);
expect(spy).toHaveBeenCalledTimes(2);
- expect(spy.calls.argsFor(0)).toEqual([
+ expect(vi.mocked(spy).mock.calls[0]).toEqual([
{ configId: 'configId1', authority: 'some-authority1' },
allConfigs,
undefined,
]);
- expect(spy.calls.argsFor(1)).toEqual([
+ expect(vi.mocked(spy).mock.calls[1]).toEqual([
{ configId: 'configId2', authority: 'some-authority2' },
allConfigs,
undefined,
]);
});
- }));
+ });
- it('throws error if url has state param but no config could be found', waitForAsync(() => {
- spyOn(currentUrlService, 'getStateParamFromCurrentUrl').and.returnValue(
- 'the-state-param'
- );
+ it('throws error if url has state param but no config could be found', async () => {
+ vi.spyOn(
+ currentUrlService,
+ 'getStateParamFromCurrentUrl'
+ ).mockReturnValue('the-state-param');
const allConfigs: OpenIdConfiguration[] = [];
@@ -902,6 +911,6 @@ describe('CheckAuthService', () => {
);
},
});
- }));
+ });
});
});
diff --git a/src/auth-state/check-auth.service.ts b/src/auth-state/check-auth.service.ts
index eaddadc..b2d6d9c 100644
--- a/src/auth-state/check-auth.service.ts
+++ b/src/auth-state/check-auth.service.ts
@@ -1,15 +1,15 @@
-import { inject, Injectable } from 'injection-js';
-import { forkJoin, Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, forkJoin, of, throwError } from 'rxjs';
import { catchError, map, switchMap, tap } from 'rxjs/operators';
import { AutoLoginService } from '../auto-login/auto-login.service';
import { CallbackService } from '../callback/callback.service';
import { PeriodicallyTokenCheckService } from '../callback/periodically-token-check.service';
import { RefreshSessionService } from '../callback/refresh-session.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { CheckSessionService } from '../iframe/check-session.service';
import { SilentRenewService } from '../iframe/silent-renew.service';
import { LoggerService } from '../logging/logger.service';
-import { LoginResponse } from '../login/login-response';
+import type { LoginResponse } from '../login/login-response';
import { PopUpService } from '../login/popup/popup.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
diff --git a/src/auth.module.spec.ts b/src/auth.module.spec.ts
index 8e06b77..2507550 100644
--- a/src/auth.module.spec.ts
+++ b/src/auth.module.spec.ts
@@ -1,6 +1,6 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../test/auto-mock';
+import { vi } from 'vitest';
import { PASSED_CONFIG } from './auth-config';
import { AuthModule } from './auth.module';
import { ConfigurationService } from './config/config.service';
@@ -9,19 +9,20 @@ import {
StsConfigLoader,
StsConfigStaticLoader,
} from './config/loader/config-loader';
+import { mockProvider } from './testing/mock';
describe('AuthModule', () => {
describe('APP_CONFIG', () => {
- beforeEach(waitForAsync(() => {
- TestBed.configureTestingModule({
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
imports: [AuthModule.forRoot({ config: { authority: 'something' } })],
providers: [mockProvider(ConfigurationService)],
}).compileComponents();
- }));
+ });
it('should create', () => {
expect(AuthModule).toBeDefined();
- expect(AuthModule.forRoot({})).toBeDefined();
+ expect(new AuthModule()).toBeDefined();
});
it('should provide config', () => {
@@ -38,8 +39,8 @@ describe('AuthModule', () => {
});
describe('StsConfigHttpLoader', () => {
- beforeEach(waitForAsync(() => {
- TestBed.configureTestingModule({
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
imports: [
AuthModule.forRoot({
loader: {
@@ -50,7 +51,7 @@ describe('AuthModule', () => {
],
providers: [mockProvider(ConfigurationService)],
}).compileComponents();
- }));
+ });
it('should create StsConfigStaticLoader if config is passed', () => {
const configLoader = TestBed.inject(StsConfigLoader);
diff --git a/src/auth.module.ts b/src/auth.module.ts
index 79c734c..a3e2b6b 100644
--- a/src/auth.module.ts
+++ b/src/auth.module.ts
@@ -1,25 +1,41 @@
-import { CommonModule } from '@angular/common';
import {
- provideHttpClient,
- withInterceptorsFromDi,
-} from '@ngify/http';
-import { ModuleWithProviders, NgModule } from 'injection-js';
-import { PassedInitialConfig } from './auth-config';
+ type InjectionToken,
+ Injector,
+ ReflectiveInjector,
+ type Type,
+} from 'injection-js';
+import type { PassedInitialConfig } from './auth-config';
+import type { Module } from './injection';
import { _provideAuth } from './provide-auth';
-@NgModule({
- declarations: [],
- exports: [],
- imports: [CommonModule],
- providers: [provideHttpClient(withInterceptorsFromDi())],
-})
-export class AuthModule {
- static forRoot(
- passedConfig: PassedInitialConfig
- ): ModuleWithProviders {
- return {
- ngModule: AuthModule,
- providers: [..._provideAuth(passedConfig)],
- };
+export interface AuthModuleOptions {
+ passedConfig: PassedInitialConfig;
+ parentInjector?: ReflectiveInjector;
+}
+
+export class AuthModule extends Injector {
+ passedConfig: PassedInitialConfig;
+ injector: ReflectiveInjector;
+ parentInjector?: Injector;
+
+ constructor(passedConfig?: PassedInitialConfig, parentInjector?: Injector) {
+ super();
+ this.passedConfig = passedConfig ?? {};
+ this.parentInjector = parentInjector;
+ this.injector = ReflectiveInjector.resolveAndCreate(
+ [..._provideAuth(this.passedConfig)],
+ this.parentInjector
+ );
+ }
+
+ static forRoot(passedConfig?: PassedInitialConfig): Module {
+ return (parentInjector?: Injector) =>
+ new AuthModule(passedConfig, parentInjector);
+ }
+
+ get(token: Type | InjectionToken, notFoundValue?: T): T;
+ get(token: any, notFoundValue?: any);
+ get(token: unknown, notFoundValue?: unknown): any {
+ return this.injector.get(token, notFoundValue);
}
}
diff --git a/src/auto-login/auto-login-partial-routes.guard.spec.ts b/src/auto-login/auto-login-partial-routes.guard.spec.ts
index 672e12b..3e0b55c 100644
--- a/src/auto-login/auto-login-partial-routes.guard.spec.ts
+++ b/src/auto-login/auto-login-partial-routes.guard.spec.ts
@@ -1,17 +1,17 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockRouterProvider } from '@/testing';
import {
- ActivatedRouteSnapshot,
- Router,
- RouterStateSnapshot,
-} from '@angular/router';
-import { RouterTestingModule } from '@angular/router/testing';
+ AbstractRouter,
+ type ActivatedRouteSnapshot,
+ type RouterStateSnapshot,
+} from 'oidc-client-rx';
import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { CheckAuthService } from '../auth-state/check-auth.service';
import { ConfigurationService } from '../config/config.service';
import { LoginService } from '../login/login.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import {
AutoLoginPartialRoutesGuard,
autoLoginPartialRoutesGuard,
@@ -19,11 +19,12 @@ import {
} from './auto-login-partial-routes.guard';
import { AutoLoginService } from './auto-login.service';
-describe(`AutoLoginPartialRoutesGuard`, () => {
+describe('AutoLoginPartialRoutesGuard', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule],
+ imports: [],
providers: [
+ mockRouterProvider(),
AutoLoginService,
mockProvider(AuthStateService),
mockProvider(LoginService),
@@ -41,7 +42,7 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
let storagePersistenceService: StoragePersistenceService;
let configurationService: ConfigurationService;
let autoLoginService: AutoLoginService;
- let router: Router;
+ let router: AbstractRouter;
beforeEach(() => {
authStateService = TestBed.inject(AuthStateService);
@@ -49,15 +50,16 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
storagePersistenceService = TestBed.inject(StoragePersistenceService);
configurationService = TestBed.inject(ConfigurationService);
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of({ configId: 'configId1' })
);
guard = TestBed.inject(AutoLoginPartialRoutesGuard);
autoLoginService = TestBed.inject(AutoLoginService);
- router = TestBed.inject(Router);
+ router = TestBed.inject(AbstractRouter);
});
+ // biome-ignore lint/correctness/noUndeclaredVariables:
afterEach(() => {
storagePersistenceService.clear({});
});
@@ -67,19 +69,19 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
});
describe('canActivate', () => {
- it('should save current route and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivate(
@@ -87,32 +89,32 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
{ url: 'some-url1' } as RouterStateSnapshot
)
.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url1'
);
- expect(loginSpy).toHaveBeenCalledOnceWith({
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1',
});
expect(
checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled();
});
- }));
+ });
- it('should save current route and call `login` if not authenticated already and add custom params', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route and call `login` if not authenticated already and add custom params', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivate(
@@ -120,11 +122,11 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
{ url: 'some-url1' } as RouterStateSnapshot
)
.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url1'
);
- expect(loginSpy).toHaveBeenCalledOnceWith(
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
{ customParams: { custom: 'param' } }
);
@@ -132,21 +134,21 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled();
});
- }));
+ });
- it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivate(
@@ -158,25 +160,25 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
expect(loginSpy).not.toHaveBeenCalled();
expect(
checkSavedRedirectRouteAndNavigateSpy
- ).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
});
- }));
+ });
});
describe('canActivateChild', () => {
- it('should save current route and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivateChild(
@@ -184,32 +186,32 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
{ url: 'some-url1' } as RouterStateSnapshot
)
.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url1'
);
- expect(loginSpy).toHaveBeenCalledOnceWith({
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1',
});
expect(
checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled();
});
- }));
+ });
- it('should save current route and call `login` if not authenticated already with custom params', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route and call `login` if not authenticated already with custom params', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivateChild(
@@ -217,11 +219,11 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
{ url: 'some-url1' } as RouterStateSnapshot
)
.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url1'
);
- expect(loginSpy).toHaveBeenCalledOnceWith(
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
{ customParams: { custom: 'param' } }
);
@@ -229,21 +231,21 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled();
});
- }));
+ });
- it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard
.canActivateChild(
@@ -255,51 +257,53 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
expect(loginSpy).not.toHaveBeenCalled();
expect(
checkSavedRedirectRouteAndNavigateSpy
- ).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
});
- }));
+ });
});
describe('canLoad', () => {
- it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route (empty) and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard.canLoad().subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
''
);
- expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
+ configId: 'configId1',
+ });
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should save current route (with router extractedUrl) and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
- spyOn(router, 'getCurrentNavigation').and.returnValue({
+ vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({
extractedUrl: router.parseUrl(
'some-url12/with/some-param?queryParam=true'
),
@@ -311,37 +315,39 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
});
guard.canLoad().subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url12/with/some-param?queryParam=true'
);
- expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
+ configId: 'configId1',
+ });
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
guard.canLoad().subscribe(() => {
expect(saveRedirectRouteSpy).not.toHaveBeenCalled();
expect(loginSpy).not.toHaveBeenCalled();
expect(
checkSavedRedirectRouteAndNavigateSpy
- ).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
});
- }));
+ });
});
});
@@ -352,7 +358,7 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
let storagePersistenceService: StoragePersistenceService;
let configurationService: ConfigurationService;
let autoLoginService: AutoLoginService;
- let router: Router;
+ let router: AbstractRouter;
beforeEach(() => {
authStateService = TestBed.inject(AuthStateService);
@@ -360,48 +366,52 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
storagePersistenceService = TestBed.inject(StoragePersistenceService);
configurationService = TestBed.inject(ConfigurationService);
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
- of({ configId: 'configId1' })
- );
+ vi.spyOn(
+ configurationService,
+ 'getOpenIDConfiguration'
+ ).mockReturnValue(of({ configId: 'configId1' }));
autoLoginService = TestBed.inject(AutoLoginService);
- router = TestBed.inject(Router);
+ router = TestBed.inject(AbstractRouter);
});
+ // biome-ignore lint/correctness/noUndeclaredVariables:
afterEach(() => {
storagePersistenceService.clear({});
});
- it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route (empty) and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
const guard$ = TestBed.runInInjectionContext(
autoLoginPartialRoutesGuard
);
guard$.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
''
);
- expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
+ configId: 'configId1',
+ });
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should save current route (with router extractedUrl) and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(router, 'getCurrentNavigation').and.returnValue({
+ it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
+ vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({
extractedUrl: router.parseUrl(
'some-url12/with/some-param?queryParam=true'
),
@@ -412,46 +422,48 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
trigger: 'imperative',
});
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
const guard$ = TestBed.runInInjectionContext(
autoLoginPartialRoutesGuard
);
guard$.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'some-url12/with/some-param?queryParam=true'
);
- expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
+ configId: 'configId1',
+ });
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should save current route and call `login` if not authenticated already and add custom params', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route and call `login` if not authenticated already and add custom params', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
const guard$ = TestBed.runInInjectionContext(() =>
autoLoginPartialRoutesGuard({
@@ -460,31 +472,31 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
);
guard$.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
''
);
- expect(loginSpy).toHaveBeenCalledOnceWith(
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
{ customParams: { custom: 'param' } }
);
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
const guard$ = TestBed.runInInjectionContext(
autoLoginPartialRoutesGuard
@@ -495,9 +507,9 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
expect(loginSpy).not.toHaveBeenCalled();
expect(
checkSavedRedirectRouteAndNavigateSpy
- ).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
});
- }));
+ });
});
describe('autoLoginPartialRoutesGuardWithConfig', () => {
@@ -513,44 +525,48 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
storagePersistenceService = TestBed.inject(StoragePersistenceService);
configurationService = TestBed.inject(ConfigurationService);
- spyOn(configurationService, 'getOpenIDConfiguration').and.callFake(
- (configId) => of({ configId })
- );
+ vi.spyOn(
+ configurationService,
+ 'getOpenIDConfiguration'
+ ).mockImplementation((configId) => of({ configId }));
autoLoginService = TestBed.inject(AutoLoginService);
});
+ // biome-ignore lint/correctness/noUndeclaredVariables:
afterEach(() => {
storagePersistenceService.clear({});
});
- it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ it('should save current route (empty) and call `login` if not authenticated already', async () => {
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const checkSavedRedirectRouteAndNavigateSpy = spyOn(
+ const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
autoLoginService,
'checkSavedRedirectRouteAndNavigate'
);
- const saveRedirectRouteSpy = spyOn(
+ const saveRedirectRouteSpy = vi.spyOn(
autoLoginService,
'saveRedirectRoute'
);
- const loginSpy = spyOn(loginService, 'login');
+ const loginSpy = vi.spyOn(loginService, 'login');
const guard$ = TestBed.runInInjectionContext(
autoLoginPartialRoutesGuardWithConfig('configId1')
);
guard$.subscribe(() => {
- expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
+ expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
''
);
- expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
+ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
+ configId: 'configId1',
+ });
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
});
- }));
+ });
});
});
});
diff --git a/src/auto-login/auto-login-partial-routes.guard.ts b/src/auto-login/auto-login-partial-routes.guard.ts
index 96144f1..8c50c42 100644
--- a/src/auto-login/auto-login-partial-routes.guard.ts
+++ b/src/auto-login/auto-login-partial-routes.guard.ts
@@ -1,15 +1,16 @@
-import { inject, Injectable } from 'injection-js';
-import {
- ActivatedRouteSnapshot,
- Router,
- RouterStateSnapshot,
-} from '@angular/router';
-import { Observable } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import type { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
-import { AuthOptions } from '../auth-options';
+import type { AuthOptions } from '../auth-options';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ConfigurationService } from '../config/config.service';
+import { injectAbstractType } from '../injection';
import { LoginService } from '../login/login.service';
+import {
+ AbstractRouter,
+ type ActivatedRouteSnapshot,
+ type RouterStateSnapshot,
+} from '../router';
import { AutoLoginService } from './auto-login.service';
@Injectable()
@@ -22,7 +23,7 @@ export class AutoLoginPartialRoutesGuard {
private readonly configurationService = inject(ConfigurationService);
- private readonly router = inject(Router);
+ private readonly router = injectAbstractType(AbstractRouter);
canLoad(): Observable {
const url =
@@ -79,14 +80,14 @@ export class AutoLoginPartialRoutesGuard {
export function autoLoginPartialRoutesGuard(
route?: ActivatedRouteSnapshot,
- state?: RouterStateSnapshot,
+ _state?: RouterStateSnapshot,
configId?: string
): Observable {
const configurationService = inject(ConfigurationService);
const authStateService = inject(AuthStateService);
const loginService = inject(LoginService);
const autoLoginService = inject(AutoLoginService);
- const router = inject(Router);
+ const router = injectAbstractType(AbstractRouter);
const authOptions: AuthOptions | undefined = route?.data
? { customParams: route.data }
: undefined;
diff --git a/src/auto-login/auto-login.service.spec.ts b/src/auto-login/auto-login.service.spec.ts
index b0f685a..f738c47 100644
--- a/src/auto-login/auto-login.service.spec.ts
+++ b/src/auto-login/auto-login.service.spec.ts
@@ -1,8 +1,9 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { AutoLoginService } from './auto-login.service';
describe('AutoLoginService ', () => {
@@ -29,11 +30,11 @@ describe('AutoLoginService ', () => {
describe('checkSavedRedirectRouteAndNavigate', () => {
it('if not route is saved, router and delete are not called', () => {
- const deleteSpy = spyOn(storagePersistenceService, 'remove');
- const routerSpy = spyOn(router, 'navigateByUrl');
- const readSpy = spyOn(storagePersistenceService, 'read').and.returnValue(
- null
- );
+ const deleteSpy = vi.spyOn(storagePersistenceService, 'remove');
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
+ const readSpy = vi
+ .spyOn(storagePersistenceService, 'read')
+ .mockReturnValue(null);
autoLoginService.checkSavedRedirectRouteAndNavigate({
configId: 'configId1',
@@ -41,27 +42,27 @@ describe('AutoLoginService ', () => {
expect(deleteSpy).not.toHaveBeenCalled();
expect(routerSpy).not.toHaveBeenCalled();
- expect(readSpy).toHaveBeenCalledOnceWith('redirect', {
+ expect(readSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
configId: 'configId1',
});
});
it('if route is saved, router and delete are called', () => {
- const deleteSpy = spyOn(storagePersistenceService, 'remove');
- const routerSpy = spyOn(router, 'navigateByUrl');
- const readSpy = spyOn(storagePersistenceService, 'read').and.returnValue(
- 'saved-route'
- );
+ const deleteSpy = vi.spyOn(storagePersistenceService, 'remove');
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
+ const readSpy = vi
+ .spyOn(storagePersistenceService, 'read')
+ .mockReturnValue('saved-route');
autoLoginService.checkSavedRedirectRouteAndNavigate({
configId: 'configId1',
});
- expect(deleteSpy).toHaveBeenCalledOnceWith('redirect', {
+ expect(deleteSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
configId: 'configId1',
});
- expect(routerSpy).toHaveBeenCalledOnceWith('saved-route');
- expect(readSpy).toHaveBeenCalledOnceWith('redirect', {
+ expect(routerSpy).toHaveBeenCalledExactlyOnceWith('saved-route');
+ expect(readSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
configId: 'configId1',
});
});
@@ -69,16 +70,20 @@ describe('AutoLoginService ', () => {
describe('saveRedirectRoute', () => {
it('calls storageService with correct params', () => {
- const writeSpy = spyOn(storagePersistenceService, 'write');
+ const writeSpy = vi.spyOn(storagePersistenceService, 'write');
autoLoginService.saveRedirectRoute(
{ configId: 'configId1' },
'some-route'
);
- expect(writeSpy).toHaveBeenCalledOnceWith('redirect', 'some-route', {
- configId: 'configId1',
- });
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
+ 'redirect',
+ 'some-route',
+ {
+ configId: 'configId1',
+ }
+ );
});
});
});
diff --git a/src/callback/callback.service.spec.ts b/src/callback/callback.service.spec.ts
index 75f67b6..68fbda9 100644
--- a/src/callback/callback.service.spec.ts
+++ b/src/callback/callback.service.spec.ts
@@ -1,7 +1,8 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { Observable, of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { CallbackContext } from '../flows/callback-context';
+import { TestBed } from '@/testing';
+import { Observable, lastValueFrom, of } from 'rxjs';
+import { vi } from 'vitest';
+import type { CallbackContext } from '../flows/callback-context';
+import { mockProvider } from '../testing/mock';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { UrlService } from '../utils/url/url.service';
import { CallbackService } from './callback.service';
@@ -26,9 +27,6 @@ describe('CallbackService ', () => {
mockProvider(CodeFlowCallbackService),
],
});
- });
-
- beforeEach(() => {
callbackService = TestBed.inject(CallbackService);
flowHelper = TestBed.inject(FlowHelper);
implicitFlowCallbackService = TestBed.inject(ImplicitFlowCallbackService);
@@ -38,10 +36,13 @@ describe('CallbackService ', () => {
describe('isCallback', () => {
it('calls urlService.isCallbackFromSts with passed url', () => {
- const urlServiceSpy = spyOn(urlService, 'isCallbackFromSts');
+ const urlServiceSpy = vi.spyOn(urlService, 'isCallbackFromSts');
callbackService.isCallback('anyUrl');
- expect(urlServiceSpy).toHaveBeenCalledOnceWith('anyUrl', undefined);
+ expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith(
+ 'anyUrl',
+ undefined
+ );
});
});
@@ -52,93 +53,98 @@ describe('CallbackService ', () => {
});
describe('handleCallbackAndFireEvents', () => {
- it('calls authorizedCallbackWithCode if current flow is code flow', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- const authorizedCallbackWithCodeSpy = spyOn(
- codeFlowCallbackService,
- 'authenticatedCallbackWithCode'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls authorizedCallbackWithCode if current flow is code flow', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ const authorizedCallbackWithCodeSpy = vi
+ .spyOn(codeFlowCallbackService, 'authenticatedCallbackWithCode')
+ .mockReturnValue(of({} as CallbackContext));
- callbackService
- .handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
+ await lastValueFrom(
+ callbackService.handleCallbackAndFireEvents(
+ 'anyUrl',
{ configId: 'configId1' },
- ])
- .subscribe(() => {
- expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledOnceWith(
- 'anyUrl',
- { configId: 'configId1' },
- [{ configId: 'configId1' }]
- );
- });
- }));
+ [{ configId: 'configId1' }]
+ )
+ );
- it('calls authorizedImplicitFlowCallback without hash if current flow is implicit flow and callbackurl does not include a hash', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
- const authorizedCallbackWithCodeSpy = spyOn(
- implicitFlowCallbackService,
- 'authenticatedImplicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledExactlyOnceWith(
+ 'anyUrl',
+ { configId: 'configId1' },
+ [{ configId: 'configId1' }]
+ );
+ });
- callbackService
- .handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
+ it('calls authorizedImplicitFlowCallback without hash if current flow is implicit flow and callbackurl does not include a hash', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
+ true
+ );
+ const authorizedCallbackWithCodeSpy = vi
+ .spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
+
+ await lastValueFrom(
+ callbackService.handleCallbackAndFireEvents(
+ 'anyUrl',
{ configId: 'configId1' },
- ])
- .subscribe(() => {
- expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
- { configId: 'configId1' },
- [{ configId: 'configId1' }]
- );
- });
- }));
+ [{ configId: 'configId1' }]
+ )
+ );
+ expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
+ { configId: 'configId1' },
+ [{ configId: 'configId1' }]
+ );
+ });
- it('calls authorizedImplicitFlowCallback with hash if current flow is implicit flow and callbackurl does include a hash', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
- const authorizedCallbackWithCodeSpy = spyOn(
- implicitFlowCallbackService,
- 'authenticatedImplicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls authorizedImplicitFlowCallback with hash if current flow is implicit flow and callbackurl does include a hash', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
+ true
+ );
+ const authorizedCallbackWithCodeSpy = vi
+ .spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
- callbackService
- .handleCallbackAndFireEvents(
+ await lastValueFrom(
+ callbackService.handleCallbackAndFireEvents(
'anyUrlWithAHash#some-string',
{ configId: 'configId1' },
[{ configId: 'configId1' }]
)
- .subscribe(() => {
- expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
- { configId: 'configId1' },
- [{ configId: 'configId1' }],
- 'some-string'
- );
- });
- }));
+ );
- it('emits callbackinternal no matter which flow it is', waitForAsync(() => {
- const callbackSpy = spyOn(
+ expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
+ { configId: 'configId1' },
+ [{ configId: 'configId1' }],
+ 'some-string'
+ );
+ });
+
+ it('emits callbackinternal no matter which flow it is', async () => {
+ const callbackSpy = vi.spyOn(
(callbackService as any).stsCallbackInternal$,
'next'
);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- const authenticatedCallbackWithCodeSpy = spyOn(
- codeFlowCallbackService,
- 'authenticatedCallbackWithCode'
- ).and.returnValue(of({} as CallbackContext));
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ const authenticatedCallbackWithCodeSpy = vi
+ .spyOn(codeFlowCallbackService, 'authenticatedCallbackWithCode')
+ .mockReturnValue(of({} as CallbackContext));
- callbackService
- .handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
+ await lastValueFrom(
+ callbackService.handleCallbackAndFireEvents(
+ 'anyUrl',
{ configId: 'configId1' },
- ])
- .subscribe(() => {
- expect(authenticatedCallbackWithCodeSpy).toHaveBeenCalledOnceWith(
- 'anyUrl',
- { configId: 'configId1' },
- [{ configId: 'configId1' }]
- );
- expect(callbackSpy).toHaveBeenCalled();
- });
- }));
+ [{ configId: 'configId1' }]
+ )
+ );
+
+ expect(authenticatedCallbackWithCodeSpy).toHaveBeenCalledExactlyOnceWith(
+ 'anyUrl',
+ { configId: 'configId1' },
+ [{ configId: 'configId1' }]
+ );
+ expect(callbackSpy).toHaveBeenCalled();
+ });
});
});
diff --git a/src/callback/callback.service.ts b/src/callback/callback.service.ts
index 7af6984..f4e529d 100644
--- a/src/callback/callback.service.ts
+++ b/src/callback/callback.service.ts
@@ -1,8 +1,8 @@
-import { inject, Injectable } from 'injection-js';
+import { Injectable, inject } from 'injection-js';
import { Observable, Subject } from 'rxjs';
import { tap } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { UrlService } from '../utils/url/url.service';
import { CodeFlowCallbackService } from './code-flow-callback.service';
diff --git a/src/callback/code-flow-callback.service.spec.ts b/src/callback/code-flow-callback.service.spec.ts
index 3e9996c..81c3438 100644
--- a/src/callback/code-flow-callback.service.spec.ts
+++ b/src/callback/code-flow-callback.service.spec.ts
@@ -1,11 +1,11 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { Router } from '@angular/router';
-import { RouterTestingModule } from '@angular/router/testing';
+import { TestBed, mockRouterProvider } from '@/testing';
+import { AbstractRouter } from 'oidc-client-rx';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { CallbackContext } from '../flows/callback-context';
+import { vi } from 'vitest';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
+import { mockProvider } from '../testing/mock';
import { CodeFlowCallbackService } from './code-flow-callback.service';
import { IntervalService } from './interval.service';
@@ -14,26 +14,24 @@ describe('CodeFlowCallbackService ', () => {
let intervalService: IntervalService;
let flowsService: FlowsService;
let flowsDataService: FlowsDataService;
- let router: Router;
+ let router: AbstractRouter;
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule],
+ imports: [],
providers: [
+ mockRouterProvider(),
CodeFlowCallbackService,
mockProvider(FlowsService),
mockProvider(FlowsDataService),
mockProvider(IntervalService),
],
});
- });
-
- beforeEach(() => {
codeFlowCallbackService = TestBed.inject(CodeFlowCallbackService);
intervalService = TestBed.inject(IntervalService);
flowsDataService = TestBed.inject(FlowsDataService);
flowsService = TestBed.inject(FlowsService);
- router = TestBed.inject(Router);
+ router = TestBed.inject(AbstractRouter);
});
it('should create', () => {
@@ -42,11 +40,10 @@ describe('CodeFlowCallbackService ', () => {
describe('authenticatedCallbackWithCode', () => {
it('calls flowsService.processCodeFlowCallback with correct url', () => {
- const spy = spyOn(
- flowsService,
- 'processCodeFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
- //spyOn(configurationProvider, 'getOpenIDConfiguration').and.returnValue({ triggerAuthorizationResultEvent: true });
+ const spy = vi
+ .spyOn(flowsService, 'processCodeFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
+ //spyOn(configurationProvider, 'getOpenIDConfiguration').mockReturnValue({ triggerAuthorizationResultEvent: true });
const config = {
configId: 'configId1',
@@ -58,10 +55,12 @@ describe('CodeFlowCallbackService ', () => {
config,
[config]
);
- expect(spy).toHaveBeenCalledOnceWith('some-url1', config, [config]);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-url1', config, [
+ config,
+ ]);
});
- it('does only call resetCodeFlowInProgress if triggerAuthorizationResultEvent is true and isRenewProcess is true', waitForAsync(() => {
+ it('does only call resetCodeFlowInProgress if triggerAuthorizationResultEvent is true and isRenewProcess is true', async () => {
const callbackContext = {
code: '',
refreshToken: '',
@@ -73,12 +72,14 @@ describe('CodeFlowCallbackService ', () => {
validationResult: null,
existingIdToken: '',
};
- const spy = spyOn(
- flowsService,
- 'processCodeFlowCallback'
- ).and.returnValue(of(callbackContext));
- const flowsDataSpy = spyOn(flowsDataService, 'resetCodeFlowInProgress');
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const spy = vi
+ .spyOn(flowsService, 'processCodeFlowCallback')
+ .mockReturnValue(of(callbackContext));
+ const flowsDataSpy = vi.spyOn(
+ flowsDataService,
+ 'resetCodeFlowInProgress'
+ );
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: true,
@@ -87,13 +88,15 @@ describe('CodeFlowCallbackService ', () => {
codeFlowCallbackService
.authenticatedCallbackWithCode('some-url2', config, [config])
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-url2', config, [config]);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [
+ config,
+ ]);
expect(routerSpy).not.toHaveBeenCalled();
expect(flowsDataSpy).toHaveBeenCalled();
});
- }));
+ });
- it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', waitForAsync(() => {
+ it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
const callbackContext = {
code: '',
refreshToken: '',
@@ -105,12 +108,14 @@ describe('CodeFlowCallbackService ', () => {
validationResult: null,
existingIdToken: '',
};
- const spy = spyOn(
- flowsService,
- 'processCodeFlowCallback'
- ).and.returnValue(of(callbackContext));
- const flowsDataSpy = spyOn(flowsDataService, 'resetCodeFlowInProgress');
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const spy = vi
+ .spyOn(flowsService, 'processCodeFlowCallback')
+ .mockReturnValue(of(callbackContext));
+ const flowsDataSpy = vi.spyOn(
+ flowsDataService,
+ 'resetCodeFlowInProgress'
+ );
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: false,
@@ -120,25 +125,27 @@ describe('CodeFlowCallbackService ', () => {
codeFlowCallbackService
.authenticatedCallbackWithCode('some-url3', config, [config])
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-url3', config, [config]);
- expect(routerSpy).toHaveBeenCalledOnceWith('postLoginRoute');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [
+ config,
+ ]);
+ expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
expect(flowsDataSpy).toHaveBeenCalled();
});
- }));
+ });
- it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', waitForAsync(() => {
- spyOn(flowsService, 'processCodeFlowCallback').and.returnValue(
+ it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', async () => {
+ vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue(
throwError(() => new Error('error'))
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- const resetCodeFlowInProgressSpy = spyOn(
+ const resetCodeFlowInProgressSpy = vi.spyOn(
flowsDataService,
'resetCodeFlowInProgress'
);
- const stopPeriodicallTokenCheckSpy = spyOn(
+ const stopPeriodicallTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
@@ -159,23 +166,23 @@ describe('CodeFlowCallbackService ', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
it(`navigates to unauthorizedRoute in case of error and in case of error and
- triggerAuthorizationResultEvent is false`, waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(flowsService, 'processCodeFlowCallback').and.returnValue(
+ triggerAuthorizationResultEvent is false`, async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue(
throwError(() => new Error('error'))
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- const stopPeriodicallTokenCheckSpy = spyOn(
+ const stopPeriodicallTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
@@ -190,9 +197,11 @@ describe('CodeFlowCallbackService ', () => {
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
expect(err).toBeTruthy();
- expect(routerSpy).toHaveBeenCalledOnceWith('unauthorizedRoute');
+ expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
+ 'unauthorizedRoute'
+ );
},
});
- }));
+ });
});
});
diff --git a/src/callback/code-flow-callback.service.ts b/src/callback/code-flow-callback.service.ts
index 21374f4..b3c52a9 100644
--- a/src/callback/code-flow-callback.service.ts
+++ b/src/callback/code-flow-callback.service.ts
@@ -1,9 +1,9 @@
-import { inject, Injectable } from 'injection-js';
import { Router } from '@angular/router';
-import { Observable, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
import { IntervalService } from './interval.service';
diff --git a/src/callback/implicit-flow-callback.service.spec.ts b/src/callback/implicit-flow-callback.service.spec.ts
index 830de5e..ebe7f1c 100644
--- a/src/callback/implicit-flow-callback.service.spec.ts
+++ b/src/callback/implicit-flow-callback.service.spec.ts
@@ -1,11 +1,11 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { Router } from '@angular/router';
-import { RouterTestingModule } from '@angular/router/testing';
+import { TestBed, mockRouterProvider } from '@/testing';
+import { AbstractRouter } from 'oidc-client-rx';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { CallbackContext } from '../flows/callback-context';
+import { vi } from 'vitest';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
+import { mockProvider } from '../testing/mock';
import { ImplicitFlowCallbackService } from './implicit-flow-callback.service';
import { IntervalService } from './interval.service';
@@ -14,25 +14,23 @@ describe('ImplicitFlowCallbackService ', () => {
let intervalService: IntervalService;
let flowsService: FlowsService;
let flowsDataService: FlowsDataService;
- let router: Router;
+ let router: AbstractRouter;
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule],
+ imports: [],
providers: [
+ mockRouterProvider(),
mockProvider(FlowsService),
mockProvider(FlowsDataService),
mockProvider(IntervalService),
],
});
- });
-
- beforeEach(() => {
implicitFlowCallbackService = TestBed.inject(ImplicitFlowCallbackService);
intervalService = TestBed.inject(IntervalService);
flowsDataService = TestBed.inject(FlowsDataService);
flowsService = TestBed.inject(FlowsService);
- router = TestBed.inject(Router);
+ router = TestBed.inject(AbstractRouter);
});
it('should create', () => {
@@ -41,10 +39,9 @@ describe('ImplicitFlowCallbackService ', () => {
describe('authorizedImplicitFlowCallback', () => {
it('calls flowsService.processImplicitFlowCallback with hash if given', () => {
- const spy = spyOn(
- flowsService,
- 'processImplicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ const spy = vi
+ .spyOn(flowsService, 'processImplicitFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: true,
@@ -56,10 +53,14 @@ describe('ImplicitFlowCallbackService ', () => {
'some-hash'
);
- expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ 'some-hash'
+ );
});
- it('does nothing if triggerAuthorizationResultEvent is true and isRenewProcess is true', waitForAsync(() => {
+ it('does nothing if triggerAuthorizationResultEvent is true and isRenewProcess is true', async () => {
const callbackContext = {
code: '',
refreshToken: '',
@@ -71,11 +72,10 @@ describe('ImplicitFlowCallbackService ', () => {
validationResult: null,
existingIdToken: '',
};
- const spy = spyOn(
- flowsService,
- 'processImplicitFlowCallback'
- ).and.returnValue(of(callbackContext));
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const spy = vi
+ .spyOn(flowsService, 'processImplicitFlowCallback')
+ .mockReturnValue(of(callbackContext));
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: true,
@@ -84,12 +84,16 @@ describe('ImplicitFlowCallbackService ', () => {
implicitFlowCallbackService
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ 'some-hash'
+ );
expect(routerSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', waitForAsync(() => {
+ it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
const callbackContext = {
code: '',
refreshToken: '',
@@ -101,11 +105,10 @@ describe('ImplicitFlowCallbackService ', () => {
validationResult: null,
existingIdToken: '',
};
- const spy = spyOn(
- flowsService,
- 'processImplicitFlowCallback'
- ).and.returnValue(of(callbackContext));
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const spy = vi
+ .spyOn(flowsService, 'processImplicitFlowCallback')
+ .mockReturnValue(of(callbackContext));
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: false,
@@ -115,20 +118,24 @@ describe('ImplicitFlowCallbackService ', () => {
implicitFlowCallbackService
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
- expect(routerSpy).toHaveBeenCalledOnceWith('postLoginRoute');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ 'some-hash'
+ );
+ expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
});
- }));
+ });
- it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', waitForAsync(() => {
- spyOn(flowsService, 'processImplicitFlowCallback').and.returnValue(
+ it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', async () => {
+ vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue(
throwError(() => new Error('error'))
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- const stopPeriodicallyTokenCheckSpy = spyOn(
+ const stopPeriodicallyTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
@@ -147,23 +154,23 @@ describe('ImplicitFlowCallbackService ', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
it(`navigates to unauthorizedRoute in case of error and in case of error and
- triggerAuthorizationResultEvent is false`, waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(flowsService, 'processImplicitFlowCallback').and.returnValue(
+ triggerAuthorizationResultEvent is false`, async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue(
throwError(() => new Error('error'))
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- const stopPeriodicallTokenCheckSpy = spyOn(
+ const stopPeriodicallTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
- const routerSpy = spyOn(router, 'navigateByUrl');
+ const routerSpy = vi.spyOn(router, 'navigateByUrl');
const config = {
configId: 'configId1',
triggerAuthorizationResultEvent: false,
@@ -177,9 +184,11 @@ describe('ImplicitFlowCallbackService ', () => {
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
expect(err).toBeTruthy();
- expect(routerSpy).toHaveBeenCalledOnceWith('unauthorizedRoute');
+ expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
+ 'unauthorizedRoute'
+ );
},
});
- }));
+ });
});
});
diff --git a/src/callback/implicit-flow-callback.service.ts b/src/callback/implicit-flow-callback.service.ts
index f52de47..a72d87b 100644
--- a/src/callback/implicit-flow-callback.service.ts
+++ b/src/callback/implicit-flow-callback.service.ts
@@ -1,9 +1,9 @@
-import { inject, Injectable } from 'injection-js';
import { Router } from '@angular/router';
-import { Observable, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
import { IntervalService } from './interval.service';
diff --git a/src/callback/interval.service.spec.ts b/src/callback/interval.service.spec.ts
index 2e124f5..25568c0 100644
--- a/src/callback/interval.service.spec.ts
+++ b/src/callback/interval.service.spec.ts
@@ -1,5 +1,6 @@
-import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { TestBed, fakeAsync, tick } from '@/testing';
import { Subscription } from 'rxjs';
+import { vi } from 'vitest';
import { IntervalService } from './interval.service';
describe('IntervalService', () => {
@@ -31,7 +32,7 @@ describe('IntervalService', () => {
describe('stopPeriodicTokenCheck', () => {
it('calls unsubscribe and sets to null', () => {
intervalService.runTokenValidationRunning = new Subscription();
- const spy = spyOn(
+ const spy = vi.spyOn(
intervalService.runTokenValidationRunning,
'unsubscribe'
);
@@ -44,7 +45,7 @@ describe('IntervalService', () => {
it('does nothing if `runTokenValidationRunning` is null', () => {
intervalService.runTokenValidationRunning = new Subscription();
- const spy = spyOn(
+ const spy = vi.spyOn(
intervalService.runTokenValidationRunning,
'unsubscribe'
);
@@ -57,7 +58,7 @@ describe('IntervalService', () => {
});
describe('startPeriodicTokenCheck', () => {
- it('starts check after correct milliseconds', fakeAsync(() => {
+ it('starts check after correct milliseconds', async () => {
const periodicCheck = intervalService.startPeriodicTokenCheck(0.5);
const spy = jasmine.createSpy();
const sub = periodicCheck.subscribe(() => {
@@ -71,6 +72,6 @@ describe('IntervalService', () => {
expect(spy).toHaveBeenCalledTimes(2);
sub.unsubscribe();
- }));
+ });
});
});
diff --git a/src/callback/interval.service.ts b/src/callback/interval.service.ts
index c8bbd6d..ee32b7c 100644
--- a/src/callback/interval.service.ts
+++ b/src/callback/interval.service.ts
@@ -1,11 +1,9 @@
-import { Injectable, NgZone, inject } from 'injection-js';
-import { Observable, Subscription } from 'rxjs';
-import { DOCUMENT } from '../../dom';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, type Subscription, interval } from 'rxjs';
+import { DOCUMENT } from '../dom';
@Injectable()
export class IntervalService {
- private readonly zone = inject(NgZone);
-
private readonly document = inject(DOCUMENT);
runTokenValidationRunning: Subscription | null = null;
@@ -24,19 +22,6 @@ export class IntervalService {
startPeriodicTokenCheck(repeatAfterSeconds: number): Observable {
const millisecondsDelayBetweenTokenCheck = repeatAfterSeconds * 1000;
- return new Observable((subscriber) => {
- let intervalId: number | undefined;
-
- this.zone.runOutsideAngular(() => {
- intervalId = this.document?.defaultView?.setInterval(
- () => this.zone.run(() => subscriber.next()),
- millisecondsDelayBetweenTokenCheck
- );
- });
-
- return (): void => {
- clearInterval(intervalId);
- };
- });
+ return interval(millisecondsDelayBetweenTokenCheck);
}
}
diff --git a/src/callback/periodically-token-check.service.spec.ts b/src/callback/periodically-token-check.service.spec.ts
index 93e470e..20efef3 100644
--- a/src/callback/periodically-token-check.service.spec.ts
+++ b/src/callback/periodically-token-check.service.spec.ts
@@ -1,10 +1,10 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
-import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { lastValueFrom, of, throwError } from 'rxjs';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ConfigurationService } from '../config/config.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
@@ -12,6 +12,7 @@ import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { UserService } from '../user-data/user.service';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { IntervalService } from './interval.service';
@@ -49,9 +50,6 @@ describe('PeriodicallyTokenCheckService', () => {
mockProvider(ConfigurationService),
],
});
- });
-
- beforeEach(() => {
periodicallyTokenCheckService = TestBed.inject(
PeriodicallyTokenCheckService
);
@@ -68,11 +66,14 @@ describe('PeriodicallyTokenCheckService', () => {
publicEventsService = TestBed.inject(PublicEventsService);
configurationService = TestBed.inject(ConfigurationService);
- spyOn(intervalService, 'startPeriodicTokenCheck').and.returnValue(of(null));
+ vi.spyOn(intervalService, 'startPeriodicTokenCheck').mockReturnValue(
+ of(null)
+ );
});
+ // biome-ignore lint/correctness/noUndeclaredVariables:
afterEach(() => {
- if (!!intervalService.runTokenValidationRunning?.unsubscribe) {
+ if (intervalService.runTokenValidationRunning?.unsubscribe) {
intervalService.runTokenValidationRunning.unsubscribe();
intervalService.runTokenValidationRunning = null;
}
@@ -83,164 +84,172 @@ describe('PeriodicallyTokenCheckService', () => {
});
describe('startTokenValidationPeriodically', () => {
- it('returns if no config has silentrenew enabled', waitForAsync(() => {
+ it('returns if no config has silentrenew enabled', async () => {
const configs = [
{ silentRenew: false, configId: 'configId1' },
{ silentRenew: false, configId: 'configId2' },
];
- const result =
+ const result = await lastValueFrom(
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
- );
+ configs[0]!
+ )
+ );
expect(result).toBeUndefined();
- }));
+ });
- it('returns if runTokenValidationRunning', waitForAsync(() => {
+ it('returns if runTokenValidationRunning', async () => {
const configs = [{ silentRenew: true, configId: 'configId1' }];
- spyOn(intervalService, 'isTokenValidationRunning').and.returnValue(true);
+ vi.spyOn(intervalService, 'isTokenValidationRunning').mockReturnValue(
+ true
+ );
- const result =
+ const result = await lastValueFrom(
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
- );
+ configs[0]!
+ )
+ );
expect(result).toBeUndefined();
- }));
+ });
- it('interval calls resetSilentRenewRunning when current flow is CodeFlowWithRefreshTokens', fakeAsync(() => {
+ it('interval calls resetSilentRenewRunning when current flow is CodeFlowWithRefreshTokens', async () => {
const configs = [
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
];
- spyOn(
+ vi.spyOn(
periodicallyTokenCheckService as any,
'shouldStartPeriodicallyCheckForConfig'
- ).and.returnValue(true);
- const isCurrentFlowCodeFlowWithRefreshTokensSpy = spyOn(
- flowHelper,
- 'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- const resetSilentRenewRunningSpy = spyOn(
+ ).mockReturnValue(true);
+ const isCurrentFlowCodeFlowWithRefreshTokensSpy = vi
+ .spyOn(flowHelper, 'isCurrentFlowCodeFlowWithRefreshTokens')
+ .mockReturnValue(true);
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- spyOn(
+ vi.spyOn(
refreshSessionRefreshTokenService,
'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
- of(configs[0])
+ ).mockReturnValue(of({} as CallbackContext));
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
+ of(configs[0]!)
);
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
+ configs[0]!
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
intervalService.runTokenValidationRunning?.unsubscribe();
intervalService.runTokenValidationRunning = null;
expect(isCurrentFlowCodeFlowWithRefreshTokensSpy).toHaveBeenCalled();
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
- }));
+ });
- it('interval calls resetSilentRenewRunning in case of error when current flow is CodeFlowWithRefreshTokens', fakeAsync(() => {
+ it('interval calls resetSilentRenewRunning in case of error when current flow is CodeFlowWithRefreshTokens', async () => {
const configs = [
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
];
- spyOn(
+ vi.spyOn(
periodicallyTokenCheckService as any,
'shouldStartPeriodicallyCheckForConfig'
- ).and.returnValue(true);
- const resetSilentRenewRunning = spyOn(
+ ).mockReturnValue(true);
+ const resetSilentRenewRunning = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionRefreshTokenService,
'refreshSessionWithRefreshTokens'
- ).and.returnValue(throwError(() => new Error('error')));
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
- of(configs[0])
+ ).mockReturnValue(throwError(() => new Error('error')));
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
+ of(configs[0]!)
);
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
+ configs[0]!
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
expect(
periodicallyTokenCheckService.startTokenValidationPeriodically
).toThrowError();
- expect(resetSilentRenewRunning).toHaveBeenCalledOnceWith(configs[0]);
- }));
+ expect(resetSilentRenewRunning).toHaveBeenCalledExactlyOnceWith(
+ configs[0]
+ );
+ });
- it('interval throws silent renew failed event with data in case of an error', fakeAsync(() => {
+ it('interval throws silent renew failed event with data in case of an error', async () => {
const configs = [
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
];
- spyOn(
+ vi.spyOn(
periodicallyTokenCheckService as any,
'shouldStartPeriodicallyCheckForConfig'
- ).and.returnValue(true);
- spyOn(flowsDataService, 'resetSilentRenewRunning');
- const publicEventsServiceSpy = spyOn(publicEventsService, 'fireEvent');
+ ).mockReturnValue(true);
+ vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
+ const publicEventsServiceSpy = vi.spyOn(publicEventsService, 'fireEvent');
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionRefreshTokenService,
'refreshSessionWithRefreshTokens'
- ).and.returnValue(throwError(() => new Error('error')));
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
- of(configs[0])
+ ).mockReturnValue(throwError(() => new Error('error')));
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
+ of(configs[0]!)
);
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
+ configs[0]!
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
expect(
periodicallyTokenCheckService.startTokenValidationPeriodically
).toThrowError();
- expect(publicEventsServiceSpy.calls.allArgs()).toEqual([
+ expect(publicEventsServiceSpy).toBeCalledWith([
[EventTypes.SilentRenewStarted],
[EventTypes.SilentRenewFailed, new Error('error')],
]);
- }));
+ });
- it('calls resetAuthorizationData and returns if no silent renew is configured', fakeAsync(() => {
+ it('calls resetAuthorizationData and returns if no silent renew is configured', async () => {
const configs = [
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
];
- spyOn(
+ vi.spyOn(
periodicallyTokenCheckService as any,
'shouldStartPeriodicallyCheckForConfig'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
- const configSpy = spyOn(configurationService, 'getOpenIDConfiguration');
+ const configSpy = vi.spyOn(
+ configurationService,
+ 'getOpenIDConfiguration'
+ );
const configWithoutSilentRenew = {
silentRenew: false,
configId: 'configId1',
@@ -248,68 +257,70 @@ describe('PeriodicallyTokenCheckService', () => {
};
const configWithoutSilentRenew$ = of(configWithoutSilentRenew);
- configSpy.and.returnValue(configWithoutSilentRenew$);
+ configSpy.mockReturnValue(configWithoutSilentRenew$);
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
+ configs[0]!
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
intervalService.runTokenValidationRunning?.unsubscribe();
intervalService.runTokenValidationRunning = null;
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
- expect(resetAuthorizationDataSpy).toHaveBeenCalledOnceWith(
+ expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
configWithoutSilentRenew,
configs
);
- }));
+ });
- it('calls refreshSessionWithRefreshTokens if current flow is Code flow with refresh tokens', fakeAsync(() => {
- spyOn(
+ it('calls refreshSessionWithRefreshTokens if current flow is Code flow with refresh tokens', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
periodicallyTokenCheckService as any,
'shouldStartPeriodicallyCheckForConfig'
- ).and.returnValue(true);
- spyOn(storagePersistenceService, 'read').and.returnValue({});
+ ).mockReturnValue(true);
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({});
const configs = [
{ configId: 'configId1', silentRenew: true, tokenRefreshInSeconds: 1 },
];
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(configs[0] as OpenIdConfiguration)
);
- const refreshSessionWithRefreshTokensSpy = spyOn(
- refreshSessionRefreshTokenService,
- 'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
+ const refreshSessionWithRefreshTokensSpy = vi
+ .spyOn(
+ refreshSessionRefreshTokenService,
+ 'refreshSessionWithRefreshTokens'
+ )
+ .mockReturnValue(of({} as CallbackContext));
periodicallyTokenCheckService.startTokenValidationPeriodically(
configs,
- configs[0]
+ configs[0]!
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
intervalService.runTokenValidationRunning?.unsubscribe();
intervalService.runTokenValidationRunning = null;
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
- }));
+ });
});
describe('shouldStartPeriodicallyCheckForConfig', () => {
it('returns false when there is no IdToken', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
@@ -317,13 +328,13 @@ describe('PeriodicallyTokenCheckService', () => {
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns false when silent renew is running', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
@@ -331,14 +342,14 @@ describe('PeriodicallyTokenCheckService', () => {
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns false when code flow is in progress', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(flowsDataService, 'isCodeFlowInProgress').and.returnValue(true);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(flowsDataService, 'isCodeFlowInProgress').mockReturnValue(true);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
@@ -346,87 +357,87 @@ describe('PeriodicallyTokenCheckService', () => {
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns false when there is no userdata from the store', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(null);
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(null);
const result = (
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns true when there is userDataFromStore, silentrenew is not running and there is an idtoken', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
- spyOn(
+ vi.spyOn(
authStateService,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authStateService,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const result = (
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('returns false if tokens are not expired', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
- spyOn(
+ vi.spyOn(
authStateService,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
authStateService,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = (
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns true if tokens are expired', () => {
- spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
'some-userdata'
);
- spyOn(
+ vi.spyOn(
authStateService,
'hasIdTokenExpiredAndRenewCheckIsEnabled'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authStateService,
'hasAccessTokenExpiredIfExpiryExists'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const result = (
periodicallyTokenCheckService as any
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
});
});
diff --git a/src/callback/periodically-token-check.service.ts b/src/callback/periodically-token-check.service.ts
index a5691da..1f30de6 100644
--- a/src/callback/periodically-token-check.service.ts
+++ b/src/callback/periodically-token-check.service.ts
@@ -1,10 +1,10 @@
-import { inject, Injectable } from 'injection-js';
-import { forkJoin, Observable, of, throwError } from 'rxjs';
-import { catchError, switchMap } from 'rxjs/operators';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, forkJoin, of, throwError } from 'rxjs';
+import { catchError, map, shareReplay, switchMap } from 'rxjs/operators';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ConfigurationService } from '../config/config.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
@@ -52,7 +52,7 @@ export class PeriodicallyTokenCheckService {
startTokenValidationPeriodically(
allConfigs: OpenIdConfiguration[],
currentConfig: OpenIdConfiguration
- ): void {
+ ): Observable {
const configsWithSilentRenewEnabled =
this.getConfigsWithSilentRenewEnabled(allConfigs);
@@ -75,46 +75,51 @@ export class PeriodicallyTokenCheckService {
[id: string]: Observable;
} = {};
- configsWithSilentRenewEnabled.forEach((config) => {
+ for (const config of configsWithSilentRenewEnabled) {
const identifier = config.configId as string;
const refreshEvent = this.getRefreshEvent(config, allConfigs);
objectWithConfigIdsAndRefreshEvent[identifier] = refreshEvent;
- });
+ }
return forkJoin(objectWithConfigIdsAndRefreshEvent);
})
);
- this.intervalService.runTokenValidationRunning = periodicallyCheck$
- .pipe(catchError((error) => throwError(() => new Error(error))))
- .subscribe({
- next: (objectWithConfigIds) => {
- for (const [configId, _] of Object.entries(objectWithConfigIds)) {
- this.configurationService
- .getOpenIDConfiguration(configId)
- .subscribe((config) => {
- this.loggerService.logDebug(
- config,
- 'silent renew, periodic check finished!'
- );
+ const o$ = periodicallyCheck$.pipe(
+ catchError((error) => throwError(() => new Error(error))),
+ map((objectWithConfigIds) => {
+ for (const [configId, _] of Object.entries(objectWithConfigIds)) {
+ this.configurationService
+ .getOpenIDConfiguration(configId)
+ .subscribe((config) => {
+ this.loggerService.logDebug(
+ config,
+ 'silent renew, periodic check finished!'
+ );
- if (
- this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)
- ) {
- this.flowsDataService.resetSilentRenewRunning(config);
- }
- });
- }
- },
- error: (error) => {
- this.loggerService.logError(
- currentConfig,
- 'silent renew failed!',
- error
- );
- },
- });
+ if (
+ this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)
+ ) {
+ this.flowsDataService.resetSilentRenewRunning(config);
+ }
+ });
+ }
+ }),
+ catchError((error) => {
+ this.loggerService.logError(
+ currentConfig,
+ 'silent renew failed!',
+ error
+ );
+ return throwError(() => error);
+ }),
+ shareReplay(1)
+ );
+
+ this.intervalService.runTokenValidationRunning = o$.subscribe();
+
+ return o$;
}
private getRefreshEvent(
diff --git a/src/callback/refresh-session-refresh-token.service.spec.ts b/src/callback/refresh-session-refresh-token.service.spec.ts
index 6aab19d..d4847ba 100644
--- a/src/callback/refresh-session-refresh-token.service.spec.ts
+++ b/src/callback/refresh-session-refresh-token.service.spec.ts
@@ -1,10 +1,11 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { CallbackContext } from '../flows/callback-context';
+import { vi } from 'vitest';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsService } from '../flows/flows.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { IntervalService } from './interval.service';
import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service';
@@ -25,9 +26,6 @@ describe('RefreshSessionRefreshTokenService', () => {
mockProvider(IntervalService),
],
});
- });
-
- beforeEach(() => {
flowsService = TestBed.inject(FlowsService);
refreshSessionRefreshTokenService = TestBed.inject(
RefreshSessionRefreshTokenService
@@ -41,10 +39,10 @@ describe('RefreshSessionRefreshTokenService', () => {
});
describe('refreshSessionWithRefreshTokens', () => {
- it('calls flowsService.processRefreshToken()', waitForAsync(() => {
- const spy = spyOn(flowsService, 'processRefreshToken').and.returnValue(
- of({} as CallbackContext)
- );
+ it('calls flowsService.processRefreshToken()', async () => {
+ const spy = vi
+ .spyOn(flowsService, 'processRefreshToken')
+ .mockReturnValue(of({} as CallbackContext));
refreshSessionRefreshTokenService
.refreshSessionWithRefreshTokens({ configId: 'configId1' }, [
@@ -53,13 +51,13 @@ describe('RefreshSessionRefreshTokenService', () => {
.subscribe(() => {
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it('resetAuthorizationData in case of error', waitForAsync(() => {
- spyOn(flowsService, 'processRefreshToken').and.returnValue(
+ it('resetAuthorizationData in case of error', async () => {
+ vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue(
throwError(() => new Error('error'))
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
@@ -74,13 +72,13 @@ describe('RefreshSessionRefreshTokenService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('finalize with stopPeriodicTokenCheck in case of error', fakeAsync(() => {
- spyOn(flowsService, 'processRefreshToken').and.returnValue(
+ it('finalize with stopPeriodicTokenCheck in case of error', async () => {
+ vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue(
throwError(() => new Error('error'))
);
- const stopPeriodicallyTokenCheckSpy = spyOn(
+ const stopPeriodicallyTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
@@ -94,8 +92,8 @@ describe('RefreshSessionRefreshTokenService', () => {
expect(err).toBeTruthy();
},
});
- tick();
+ await vi.advanceTimersByTimeAsync(0);
expect(stopPeriodicallyTokenCheckSpy).toHaveBeenCalled();
- }));
+ });
});
});
diff --git a/src/callback/refresh-session-refresh-token.service.ts b/src/callback/refresh-session-refresh-token.service.ts
index 56cd31c..63114c6 100644
--- a/src/callback/refresh-session-refresh-token.service.ts
+++ b/src/callback/refresh-session-refresh-token.service.ts
@@ -1,8 +1,8 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, throwError } from 'rxjs';
import { catchError, finalize } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsService } from '../flows/flows.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { LoggerService } from '../logging/logger.service';
diff --git a/src/callback/refresh-session.service.spec.ts b/src/callback/refresh-session.service.spec.ts
index 4cc72ec..73fca25 100644
--- a/src/callback/refresh-session.service.spec.ts
+++ b/src/callback/refresh-session.service.spec.ts
@@ -1,17 +1,18 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
+import { TestBed, fakeAsync, tick } from '@/testing';
import { of, throwError } from 'rxjs';
import { delay } from 'rxjs/operators';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { AuthWellKnownService } from '../config/auth-well-known/auth-well-known.service';
-import { CallbackContext } from '../flows/callback-context';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
import { SilentRenewService } from '../iframe/silent-renew.service';
import { LoggerService } from '../logging/logger.service';
-import { LoginResponse } from '../login/login-response';
+import type { LoginResponse } from '../login/login-response';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { UserService } from '../user-data/user.service';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service';
@@ -70,19 +71,19 @@ describe('RefreshSessionService ', () => {
});
describe('userForceRefreshSession', () => {
- it('should persist params refresh when extra custom params given and useRefreshToken is true', waitForAsync(() => {
- spyOn(
+ it('should persist params refresh when extra custom params given and useRefreshToken is true', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- const writeSpy = spyOn(storagePersistenceService, 'write');
+ const writeSpy = vi.spyOn(storagePersistenceService, 'write');
const allConfigs = [
{
configId: 'configId1',
@@ -94,26 +95,26 @@ describe('RefreshSessionService ', () => {
const extraCustomParams = { extra: 'custom' };
refreshSessionService
- .userForceRefreshSession(allConfigs[0], allConfigs, extraCustomParams)
+ .userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams)
.subscribe(() => {
- expect(writeSpy).toHaveBeenCalledOnceWith(
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsRefresh',
extraCustomParams,
allConfigs[0]
);
});
- }));
+ });
- it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', waitForAsync(() => {
- spyOn(
+ it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
const allConfigs = [
@@ -123,31 +124,31 @@ describe('RefreshSessionService ', () => {
silentRenewTimeoutInSeconds: 10,
},
];
- const writeSpy = spyOn(storagePersistenceService, 'write');
+ const writeSpy = vi.spyOn(storagePersistenceService, 'write');
const extraCustomParams = { extra: 'custom' };
refreshSessionService
- .userForceRefreshSession(allConfigs[0], allConfigs, extraCustomParams)
+ .userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams)
.subscribe(() => {
- expect(writeSpy).toHaveBeenCalledOnceWith(
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsAuthRequest',
extraCustomParams,
allConfigs[0]
);
});
- }));
+ });
- it('should NOT persist customparams if no customparams are given', waitForAsync(() => {
- spyOn(
+ it('should NOT persist customparams if no customparams are given', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
const allConfigs = [
@@ -157,20 +158,20 @@ describe('RefreshSessionService ', () => {
silentRenewTimeoutInSeconds: 10,
},
];
- const writeSpy = spyOn(storagePersistenceService, 'write');
+ const writeSpy = vi.spyOn(storagePersistenceService, 'write');
refreshSessionService
- .userForceRefreshSession(allConfigs[0], allConfigs)
+ .userForceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(writeSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('should call resetSilentRenewRunning in case of an error', waitForAsync(() => {
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ it('should call resetSilentRenewRunning in case of an error', async () => {
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
throwError(() => new Error('error'))
);
- spyOn(flowsDataService, 'resetSilentRenewRunning');
+ vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
const allConfigs = [
{
configId: 'configId1',
@@ -180,7 +181,7 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .userForceRefreshSession(allConfigs[0], allConfigs)
+ .userForceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({
next: () => {
fail('It should not return any result.');
@@ -191,16 +192,16 @@ describe('RefreshSessionService ', () => {
complete: () => {
expect(
flowsDataService.resetSilentRenewRunning
- ).toHaveBeenCalledOnceWith(allConfigs[0]);
+ ).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
},
});
- }));
+ });
- it('should call resetSilentRenewRunning in case of no error', waitForAsync(() => {
- spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
+ it('should call resetSilentRenewRunning in case of no error', async () => {
+ vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({} as LoginResponse)
);
- spyOn(flowsDataService, 'resetSilentRenewRunning');
+ vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
const allConfigs = [
{
configId: 'configId1',
@@ -210,7 +211,7 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .userForceRefreshSession(allConfigs[0], allConfigs)
+ .userForceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({
error: () => {
fail('It should not return any error.');
@@ -218,27 +219,29 @@ describe('RefreshSessionService ', () => {
complete: () => {
expect(
flowsDataService.resetSilentRenewRunning
- ).toHaveBeenCalledOnceWith(allConfigs[0]);
+ ).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
},
});
- }));
+ });
});
describe('forceRefreshSession', () => {
- it('only calls start refresh session and returns idToken and accessToken if auth is true', waitForAsync(() => {
- spyOn(
+ it('only calls start refresh session and returns idToken and accessToken if auth is true', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOn(authStateService, 'getIdToken').and.returnValue('id-token');
- spyOn(authStateService, 'getAccessToken').and.returnValue('access-token');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('id-token');
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
+ 'access-token'
+ );
const allConfigs = [
{
configId: 'configId1',
@@ -247,23 +250,23 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result.idToken).toEqual('id-token');
expect(result.accessToken).toEqual('access-token');
});
- }));
+ });
- it('only calls start refresh session and returns null if auth is false', waitForAsync(() => {
- spyOn(
+ it('only calls start refresh session and returns null if auth is false', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
const allConfigs = [
@@ -274,7 +277,7 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -285,24 +288,24 @@ describe('RefreshSessionService ', () => {
configId: 'configId1',
});
});
- }));
+ });
- it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', waitForAsync(() => {
- spyOn(
+ it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true
);
- spyOnProperty(
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(
+ ).mockReturnValue(
of({
authResult: {
id_token: 'some-id_token',
@@ -318,29 +321,29 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result.idToken).toBeDefined();
expect(result.accessToken).toBeDefined();
});
- }));
+ });
- it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', waitForAsync(() => {
- spyOn(
+ it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOnProperty(
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(of(null));
+ ).mockReturnValue(of(null));
const allConfigs = [
{
configId: 'configId1',
@@ -349,7 +352,7 @@ describe('RefreshSessionService ', () => {
];
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -360,23 +363,23 @@ describe('RefreshSessionService ', () => {
configId: 'configId1',
});
});
- }));
+ });
- it('occurs timeout error and retry mechanism exhausted max retry count throws error', fakeAsync(() => {
- spyOn(
+ it('occurs timeout error and retry mechanism exhausted max retry count throws error', async () => {
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOnProperty(
+ ).mockReturnValue(of(null));
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(of(null).pipe(delay(11000)));
+ ).mockReturnValue(of(null).pipe(delay(11000)));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
const allConfigs = [
@@ -386,14 +389,14 @@ describe('RefreshSessionService ', () => {
},
];
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
const expectedInvokeCount = MAX_RETRY_ATTEMPTS;
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({
next: () => {
fail('It should not return any result.');
@@ -407,9 +410,9 @@ describe('RefreshSessionService ', () => {
});
tick(allConfigs[0].silentRenewTimeoutInSeconds * 10000);
- }));
+ });
- it('occurs unknown error throws it to subscriber', fakeAsync(() => {
+ it('occurs unknown error throws it to subscriber', async () => {
const allConfigs = [
{
configId: 'configId1',
@@ -419,29 +422,29 @@ describe('RefreshSessionService ', () => {
const expectedErrorMessage = 'Test error message';
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOnProperty(
+ ).mockReturnValue(false);
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(of(null));
- spyOn(
+ ).mockReturnValue(of(null));
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(throwError(() => new Error(expectedErrorMessage)));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(throwError(() => new Error(expectedErrorMessage)));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- const resetSilentRenewRunningSpy = spyOn(
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({
next: () => {
fail('It should not return any result.');
@@ -452,10 +455,10 @@ describe('RefreshSessionService ', () => {
expect(resetSilentRenewRunningSpy).not.toHaveBeenCalled();
},
});
- }));
+ });
describe('NOT isCurrentFlowCodeFlowWithRefreshTokens', () => {
- it('does return null when not authenticated', waitForAsync(() => {
+ it('does return null when not authenticated', async () => {
const allConfigs = [
{
configId: 'configId1',
@@ -463,24 +466,24 @@ describe('RefreshSessionService ', () => {
},
];
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
+ ).mockReturnValue(of(null));
+ vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false
);
- spyOnProperty(
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(of(null));
+ ).mockReturnValue(of(null));
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
isAuthenticated: false,
@@ -491,9 +494,9 @@ describe('RefreshSessionService ', () => {
configId: 'configId1',
});
});
- }));
+ });
- it('return value only returns once', waitForAsync(() => {
+ it('return value only returns once', async () => {
const allConfigs = [
{
configId: 'configId1',
@@ -501,18 +504,18 @@ describe('RefreshSessionService ', () => {
},
];
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
refreshSessionService as any,
'startRefreshSession'
- ).and.returnValue(of(null));
- spyOnProperty(
+ ).mockReturnValue(of(null));
+ vi.spyOnProperty(
silentRenewService,
'refreshSessionWithIFrameCompleted$'
- ).and.returnValue(
+ ).mockReturnValue(
of({
authResult: {
id_token: 'some-id_token',
@@ -520,13 +523,12 @@ describe('RefreshSessionService ', () => {
},
} as CallbackContext)
);
- const spyInsideMap = spyOn(
- authStateService,
- 'areAuthStorageTokensValid'
- ).and.returnValue(true);
+ const spyInsideMap = vi
+ .spyOn(authStateService, 'areAuthStorageTokensValid')
+ .mockReturnValue(true);
refreshSessionService
- .forceRefreshSession(allConfigs[0], allConfigs)
+ .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => {
expect(result).toEqual({
idToken: 'some-id_token',
@@ -537,33 +539,33 @@ describe('RefreshSessionService ', () => {
});
expect(spyInsideMap).toHaveBeenCalledTimes(1);
});
- }));
+ });
});
});
describe('startRefreshSession', () => {
- it('returns null if no auth well known endpoint defined', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ it('returns null if no auth well known endpoint defined', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
(refreshSessionService as any)
.startRefreshSession()
.subscribe((result: any) => {
expect(result).toBe(null);
});
- }));
+ });
- it('returns null if silent renew Is running', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ it('returns null if silent renew Is running', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
(refreshSessionService as any)
.startRefreshSession()
.subscribe((result: any) => {
expect(result).toBe(null);
});
- }));
+ });
- it('calls `setSilentRenewRunning` when should be executed', waitForAsync(() => {
- const setSilentRenewRunningSpy = spyOn(
+ it('calls `setSilentRenewRunning` when should be executed', async () => {
+ const setSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'setSilentRenewRunning'
);
@@ -574,30 +576,30 @@ describe('RefreshSessionService ', () => {
},
];
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
refreshSessionRefreshTokenService,
'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
+ ).mockReturnValue(of({} as CallbackContext));
(refreshSessionService as any)
- .startRefreshSession(allConfigs[0], allConfigs)
+ .startRefreshSession(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(setSilentRenewRunningSpy).toHaveBeenCalled();
});
- }));
+ });
- it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', waitForAsync(() => {
- spyOn(flowsDataService, 'setSilentRenewRunning');
+ it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', async () => {
+ vi.spyOn(flowsDataService, 'setSilentRenewRunning');
const allConfigs = [
{
configId: 'configId1',
@@ -605,30 +607,32 @@ describe('RefreshSessionService ', () => {
},
];
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(true);
- const refreshSessionWithRefreshTokensSpy = spyOn(
- refreshSessionRefreshTokenService,
- 'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
+ ).mockReturnValue(true);
+ const refreshSessionWithRefreshTokensSpy = vi
+ .spyOn(
+ refreshSessionRefreshTokenService,
+ 'refreshSessionWithRefreshTokens'
+ )
+ .mockReturnValue(of({} as CallbackContext));
(refreshSessionService as any)
- .startRefreshSession(allConfigs[0], allConfigs)
+ .startRefreshSession(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
});
- }));
+ });
- it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', waitForAsync(() => {
- spyOn(flowsDataService, 'setSilentRenewRunning');
+ it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', async () => {
+ vi.spyOn(flowsDataService, 'setSilentRenewRunning');
const allConfigs = [
{
configId: 'configId1',
@@ -636,32 +640,33 @@ describe('RefreshSessionService ', () => {
},
];
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- spyOn(
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens'
- ).and.returnValue(false);
- const refreshSessionWithRefreshTokensSpy = spyOn(
- refreshSessionRefreshTokenService,
- 'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
+ ).mockReturnValue(false);
+ const refreshSessionWithRefreshTokensSpy = vi
+ .spyOn(
+ refreshSessionRefreshTokenService,
+ 'refreshSessionWithRefreshTokens'
+ )
+ .mockReturnValue(of({} as CallbackContext));
- const refreshSessionWithIframeSpy = spyOn(
- refreshSessionIframeService,
- 'refreshSessionWithIframe'
- ).and.returnValue(of(false));
+ const refreshSessionWithIframeSpy = vi
+ .spyOn(refreshSessionIframeService, 'refreshSessionWithIframe')
+ .mockReturnValue(of(false));
(refreshSessionService as any)
- .startRefreshSession(allConfigs[0], allConfigs)
+ .startRefreshSession(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(refreshSessionWithRefreshTokensSpy).not.toHaveBeenCalled();
expect(refreshSessionWithIframeSpy).toHaveBeenCalled();
});
- }));
+ });
});
});
diff --git a/src/callback/refresh-session.service.ts b/src/callback/refresh-session.service.ts
index bea2425..496da4a 100644
--- a/src/callback/refresh-session.service.ts
+++ b/src/callback/refresh-session.service.ts
@@ -1,10 +1,10 @@
-import { inject, Injectable } from 'injection-js';
+import { Injectable, inject } from 'injection-js';
import {
+ type Observable,
+ TimeoutError,
forkJoin,
- Observable,
of,
throwError,
- TimeoutError,
timer,
} from 'rxjs';
import {
@@ -18,13 +18,13 @@ import {
} from 'rxjs/operators';
import { AuthStateService } from '../auth-state/auth-state.service';
import { AuthWellKnownService } from '../config/auth-well-known/auth-well-known.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
import { SilentRenewService } from '../iframe/silent-renew.service';
import { LoggerService } from '../logging/logger.service';
-import { LoginResponse } from '../login/login-response';
+import type { LoginResponse } from '../login/login-response';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
import { UserService } from '../user-data/user.service';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
diff --git a/src/config/auth-well-known/auth-well-known-data.service.spec.ts b/src/config/auth-well-known/auth-well-known-data.service.spec.ts
index 383f906..7fe6736 100644
--- a/src/config/auth-well-known/auth-well-known-data.service.spec.ts
+++ b/src/config/auth-well-known/auth-well-known-data.service.spec.ts
@@ -1,11 +1,12 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
-import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service';
+import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
+import { mockProvider } from '../../testing/mock';
import { AuthWellKnownDataService } from './auth-well-known-data.service';
-import { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
+import type { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
const DUMMY_WELL_KNOWN_DOCUMENT = {
issuer: 'https://identity-server.test/realms/main',
@@ -51,56 +52,65 @@ describe('AuthWellKnownDataService', () => {
});
describe('getWellKnownDocument', () => {
- it('should add suffix if it does not exist on current URL', waitForAsync(() => {
- const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
- of(null)
- );
+ it('should add suffix if it does not exist on current URL', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'get')
+ .mockReturnValue(of(null));
const urlWithoutSuffix = 'myUrl';
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/openid-configuration`;
(service as any)
.getWellKnownDocument(urlWithoutSuffix, { configId: 'configId1' })
.subscribe(() => {
- expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
- configId: 'configId1',
- });
+ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
+ urlWithSuffix,
+ {
+ configId: 'configId1',
+ }
+ );
});
- }));
+ });
- it('should not add suffix if it does exist on current url', waitForAsync(() => {
- const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
- of(null)
- );
+ it('should not add suffix if it does exist on current url', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'get')
+ .mockReturnValue(of(null));
const urlWithSuffix = `myUrl/.well-known/openid-configuration`;
(service as any)
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' })
.subscribe(() => {
- expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
- configId: 'configId1',
- });
+ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
+ urlWithSuffix,
+ {
+ configId: 'configId1',
+ }
+ );
});
- }));
+ });
- it('should not add suffix if it does exist in the middle of current url', waitForAsync(() => {
- const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
- of(null)
- );
+ it('should not add suffix if it does exist in the middle of current url', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'get')
+ .mockReturnValue(of(null));
const urlWithSuffix = `myUrl/.well-known/openid-configuration/and/some/more/stuff`;
(service as any)
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' })
.subscribe(() => {
- expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
- configId: 'configId1',
- });
+ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
+ urlWithSuffix,
+ {
+ configId: 'configId1',
+ }
+ );
});
- }));
+ });
- it('should use the custom suffix provided in the config', waitForAsync(() => {
- const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
- of(null)
- );
+ it('should use the custom suffix provided in the config', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'get')
+ .mockReturnValue(of(null));
const urlWithoutSuffix = `myUrl`;
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/test-openid-configuration`;
@@ -110,15 +120,18 @@ describe('AuthWellKnownDataService', () => {
authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
})
.subscribe(() => {
- expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
- configId: 'configId1',
- authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
- });
+ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
+ urlWithSuffix,
+ {
+ configId: 'configId1',
+ authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
+ }
+ );
});
- }));
+ });
- it('should retry once', waitForAsync(() => {
- spyOn(dataService, 'get').and.returnValue(
+ it('should retry once', async () => {
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('one')),
of(DUMMY_WELL_KNOWN_DOCUMENT)
@@ -133,10 +146,10 @@ describe('AuthWellKnownDataService', () => {
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
},
});
- }));
+ });
- it('should retry twice', waitForAsync(() => {
- spyOn(dataService, 'get').and.returnValue(
+ it('should retry twice', async () => {
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('one')),
throwError(() => new Error('two')),
@@ -152,10 +165,10 @@ describe('AuthWellKnownDataService', () => {
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
},
});
- }));
+ });
- it('should fail after three tries', waitForAsync(() => {
- spyOn(dataService, 'get').and.returnValue(
+ it('should fail after three tries', async () => {
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('one')),
throwError(() => new Error('two')),
@@ -169,17 +182,16 @@ describe('AuthWellKnownDataService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
describe('getWellKnownEndPointsForConfig', () => {
- it('calling internal getWellKnownDocument and maps', waitForAsync(() => {
- spyOn(dataService, 'get').and.returnValue(of({ jwks_uri: 'jwks_uri' }));
+ it('calling internal getWellKnownDocument and maps', async () => {
+ vi.spyOn(dataService, 'get').mockReturnValue(
+ of({ jwks_uri: 'jwks_uri' })
+ );
- const spy = spyOn(
- service as any,
- 'getWellKnownDocument'
- ).and.callThrough();
+ const spy = vi.spyOn(service as any, 'getWellKnownDocument')();
service
.getWellKnownEndPointsForConfig({
@@ -191,10 +203,10 @@ describe('AuthWellKnownDataService', () => {
expect((result as any).jwks_uri).toBeUndefined();
expect(result.jwksUri).toBe('jwks_uri');
});
- }));
+ });
- it('throws error and logs if no authwellknownUrl is given', waitForAsync(() => {
- const loggerSpy = spyOn(loggerService, 'logError');
+ it('throws error and logs if no authwellknownUrl is given', async () => {
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = {
configId: 'configId1',
authWellknownEndpointUrl: undefined,
@@ -202,17 +214,19 @@ describe('AuthWellKnownDataService', () => {
service.getWellKnownEndPointsForConfig(config).subscribe({
error: (error) => {
- expect(loggerSpy).toHaveBeenCalledOnceWith(
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
config,
'no authWellknownEndpoint given!'
);
expect(error.message).toEqual('no authWellknownEndpoint given!');
},
});
- }));
+ });
- it('should merge the mapped endpoints with the provided endpoints', waitForAsync(() => {
- spyOn(dataService, 'get').and.returnValue(of(DUMMY_WELL_KNOWN_DOCUMENT));
+ it('should merge the mapped endpoints with the provided endpoints', async () => {
+ vi.spyOn(dataService, 'get').mockReturnValue(
+ of(DUMMY_WELL_KNOWN_DOCUMENT)
+ );
const expected: AuthWellKnownEndpoints = {
endSessionEndpoint: 'config-endSessionEndpoint',
@@ -232,6 +246,6 @@ describe('AuthWellKnownDataService', () => {
.subscribe((result) => {
expect(result).toEqual(jasmine.objectContaining(expected));
});
- }));
+ });
});
});
diff --git a/src/config/auth-well-known/auth-well-known.service.spec.ts b/src/config/auth-well-known/auth-well-known.service.spec.ts
index 099d93e..b35130e 100644
--- a/src/config/auth-well-known/auth-well-known.service.spec.ts
+++ b/src/config/auth-well-known/auth-well-known.service.spec.ts
@@ -1,9 +1,10 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { EventTypes } from '../../public-events/event-types';
import { PublicEventsService } from '../../public-events/public-events.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
+import { mockProvider } from '../../testing/mock';
import { AuthWellKnownDataService } from './auth-well-known-data.service';
import { AuthWellKnownService } from './auth-well-known.service';
@@ -22,9 +23,6 @@ describe('AuthWellKnownService', () => {
mockProvider(StoragePersistenceService),
],
});
- });
-
- beforeEach(() => {
service = TestBed.inject(AuthWellKnownService);
dataService = TestBed.inject(AuthWellKnownDataService);
storagePersistenceService = TestBed.inject(StoragePersistenceService);
@@ -36,7 +34,7 @@ describe('AuthWellKnownService', () => {
});
describe('getAuthWellKnownEndPoints', () => {
- it('getAuthWellKnownEndPoints throws an error if not config provided', waitForAsync(() => {
+ it('getAuthWellKnownEndPoints throws an error if not config provided', async () => {
service.queryAndStoreAuthWellKnownEndPoints(null).subscribe({
error: (error) => {
expect(error).toEqual(
@@ -46,17 +44,18 @@ describe('AuthWellKnownService', () => {
);
},
});
- }));
+ });
- it('getAuthWellKnownEndPoints calls always dataservice', waitForAsync(() => {
- const dataServiceSpy = spyOn(
- dataService,
- 'getWellKnownEndPointsForConfig'
- ).and.returnValue(of({ issuer: 'anything' }));
+ it('getAuthWellKnownEndPoints calls always dataservice', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'getWellKnownEndPointsForConfig')
+ .mockReturnValue(of({ issuer: 'anything' }));
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ issuer: 'anything' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ issuer: 'anything' })
+ );
service
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
@@ -65,18 +64,19 @@ describe('AuthWellKnownService', () => {
expect(dataServiceSpy).toHaveBeenCalled();
expect(result).toEqual({ issuer: 'anything' });
});
- }));
+ });
- it('getAuthWellKnownEndPoints stored the result if http call is made', waitForAsync(() => {
- const dataServiceSpy = spyOn(
- dataService,
- 'getWellKnownEndPointsForConfig'
- ).and.returnValue(of({ issuer: 'anything' }));
+ it('getAuthWellKnownEndPoints stored the result if http call is made', async () => {
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'getWellKnownEndPointsForConfig')
+ .mockReturnValue(of({ issuer: 'anything' }));
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue(null);
- const storeSpy = spyOn(service, 'storeWellKnownEndpoints');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => null
+ );
+ const storeSpy = vi.spyOn(service, 'storeWellKnownEndpoints');
service
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
@@ -85,13 +85,13 @@ describe('AuthWellKnownService', () => {
expect(storeSpy).toHaveBeenCalled();
expect(result).toEqual({ issuer: 'anything' });
});
- }));
+ });
- it('throws `ConfigLoadingFailed` event when error happens from http', waitForAsync(() => {
- spyOn(dataService, 'getWellKnownEndPointsForConfig').and.returnValue(
+ it('throws `ConfigLoadingFailed` event when error happens from http', async () => {
+ vi.spyOn(dataService, 'getWellKnownEndPointsForConfig').mockReturnValue(
throwError(() => new Error('error'))
);
- const publicEventsServiceSpy = spyOn(publicEventsService, 'fireEvent');
+ const publicEventsServiceSpy = vi.spyOn(publicEventsService, 'fireEvent');
service
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
@@ -99,12 +99,12 @@ describe('AuthWellKnownService', () => {
error: (err) => {
expect(err).toBeTruthy();
expect(publicEventsServiceSpy).toHaveBeenCalledTimes(1);
- expect(publicEventsServiceSpy).toHaveBeenCalledOnceWith(
+ expect(publicEventsServiceSpy).toHaveBeenCalledExactlyOnceWith(
EventTypes.ConfigLoadingFailed,
null
);
},
});
- }));
+ });
});
});
diff --git a/src/config/config.service.spec.ts b/src/config/config.service.spec.ts
index 609b314..8862ba9 100644
--- a/src/config/config.service.spec.ts
+++ b/src/config/config.service.spec.ts
@@ -1,15 +1,16 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockAbstractProvider, mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockAbstractProvider, mockProvider } from '../testing/mock';
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
import { AuthWellKnownService } from './auth-well-known/auth-well-known.service';
import { ConfigurationService } from './config.service';
import { StsConfigLoader, StsConfigStaticLoader } from './loader/config-loader';
-import { OpenIdConfiguration } from './openid-configuration';
+import type { OpenIdConfiguration } from './openid-configuration';
import { ConfigValidationService } from './validation/config-validation.service';
describe('Configuration Service', () => {
@@ -34,9 +35,6 @@ describe('Configuration Service', () => {
mockAbstractProvider(StsConfigLoader, StsConfigStaticLoader),
],
});
- });
-
- beforeEach(() => {
configService = TestBed.inject(ConfigurationService);
publicEventsService = TestBed.inject(PublicEventsService);
authWellKnownService = TestBed.inject(AuthWellKnownService);
@@ -88,47 +86,53 @@ describe('Configuration Service', () => {
});
describe('getOpenIDConfiguration', () => {
- it(`if config is already saved 'loadConfigs' is not called`, waitForAsync(() => {
+ it(`if config is already saved 'loadConfigs' is not called`, async () => {
(configService as any).configsInternal = {
configId1: { configId: 'configId1' },
configId2: { configId: 'configId2' },
};
- const spy = spyOn(configService as any, 'loadConfigs');
+ const spy = vi.spyOn(configService as any, 'loadConfigs');
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
expect(config).toBeTruthy();
expect(spy).not.toHaveBeenCalled();
});
- }));
+ });
- it(`if config is NOT already saved 'loadConfigs' is called`, waitForAsync(() => {
+ it(`if config is NOT already saved 'loadConfigs' is called`, async () => {
const configs = [{ configId: 'configId1' }, { configId: 'configId2' }];
- const spy = spyOn(configService as any, 'loadConfigs').and.returnValue(
- of(configs)
- );
+ const spy = vi
+ .spyOn(configService as any, 'loadConfigs')
+ .mockReturnValue(of(configs));
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
expect(config).toBeTruthy();
expect(spy).toHaveBeenCalled();
});
- }));
+ });
- it(`returns null if config is not valid`, waitForAsync(() => {
+ it('returns null if config is not valid', async () => {
const configs = [{ configId: 'configId1' }];
- spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
- spyOn(configValidationService, 'validateConfig').and.returnValue(false);
- const consoleSpy = spyOn(console, 'warn');
+ vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
+ of(configs)
+ );
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(
+ false
+ );
+ const consoleSpy = vi.spyOn(console, 'warn');
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
expect(config).toBeNull();
- expect(consoleSpy).toHaveBeenCalledOnceWith(`[oidc-client-rx] No configuration found for config id 'configId1'.`)
+ expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
+ `[oidc-client-rx] No configuration found for config id 'configId1'.`
+ );
});
- }));
+ });
- it(`returns null if configs are stored but not existing ID is passed`, waitForAsync(() => {
+ it('returns null if configs are stored but not existing ID is passed', async () => {
(configService as any).configsInternal = {
configId1: { configId: 'configId1' },
configId2: { configId: 'configId2' },
@@ -139,16 +143,18 @@ describe('Configuration Service', () => {
.subscribe((config) => {
expect(config).toBeNull();
});
- }));
+ });
- it(`sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored`, waitForAsync(() => {
+ it('sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored', async () => {
const configs = [{ configId: 'configId1' }];
- spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
- const consoleSpy = spyOn(console, 'warn');
+ vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
+ of(configs)
+ );
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
+ const consoleSpy = vi.spyOn(console, 'warn');
- spyOn(storagePersistenceService, 'read').and.returnValue({
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
issuer: 'auth-well-known',
});
@@ -156,30 +162,32 @@ describe('Configuration Service', () => {
expect(config?.authWellknownEndpoints).toEqual({
issuer: 'auth-well-known',
});
- expect(consoleSpy).not.toHaveBeenCalled()
+ expect(consoleSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it(`fires ConfigLoaded if authWellKnownEndPoints is stored`, waitForAsync(() => {
+ it('fires ConfigLoaded if authWellKnownEndPoints is stored', async () => {
const configs = [{ configId: 'configId1' }];
- spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
- spyOn(storagePersistenceService, 'read').and.returnValue({
+ vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
+ of(configs)
+ );
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
issuer: 'auth-well-known',
});
- const spy = spyOn(publicEventsService, 'fireEvent');
+ const spy = vi.spyOn(publicEventsService, 'fireEvent');
configService.getOpenIDConfiguration('configId1').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
EventTypes.ConfigLoaded,
- jasmine.anything()
+ expect.anything()
);
});
- }));
+ });
- it(`stores, uses and fires event when authwellknownendpoints are passed`, waitForAsync(() => {
+ it('stores, uses and fires event when authwellknownendpoints are passed', async () => {
const configs = [
{
configId: 'configId1',
@@ -187,58 +195,60 @@ describe('Configuration Service', () => {
},
];
- spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
- spyOn(storagePersistenceService, 'read').and.returnValue(null);
+ vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
+ of(configs)
+ );
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);
- const fireEventSpy = spyOn(publicEventsService, 'fireEvent');
- const storeWellKnownEndpointsSpy = spyOn(
+ const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
+ const storeWellKnownEndpointsSpy = vi.spyOn(
authWellKnownService,
'storeWellKnownEndpoints'
);
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
expect(config).toBeTruthy();
- expect(fireEventSpy).toHaveBeenCalledOnceWith(
+ expect(fireEventSpy).toHaveBeenCalledExactlyOnceWith(
EventTypes.ConfigLoaded,
- jasmine.anything()
+ expect.anything()
);
- expect(storeWellKnownEndpointsSpy).toHaveBeenCalledOnceWith(
+ expect(storeWellKnownEndpointsSpy).toHaveBeenCalledExactlyOnceWith(
config as OpenIdConfiguration,
{
issuer: 'auth-well-known',
}
);
});
- }));
+ });
});
describe('getOpenIDConfigurations', () => {
- it(`returns correct result`, waitForAsync(() => {
- spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
+ it('returns correct result', async () => {
+ vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
of([
{ configId: 'configId1' } as OpenIdConfiguration,
{ configId: 'configId2' } as OpenIdConfiguration,
])
);
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfigurations('configId1').subscribe((result) => {
expect(result.allConfigs.length).toEqual(2);
expect(result.currentConfig).toBeTruthy();
});
- }));
+ });
- it(`created configId when configId is not set`, waitForAsync(() => {
- spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
+ it('created configId when configId is not set', async () => {
+ vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
of([
{ clientId: 'clientId1' } as OpenIdConfiguration,
{ clientId: 'clientId2' } as OpenIdConfiguration,
])
);
- spyOn(configValidationService, 'validateConfig').and.returnValue(true);
+ vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfigurations().subscribe((result) => {
expect(result.allConfigs.length).toEqual(2);
@@ -249,17 +259,19 @@ describe('Configuration Service', () => {
expect(result.currentConfig).toBeTruthy();
expect(result.currentConfig?.configId).toBeTruthy();
});
- }));
+ });
- it(`returns empty array if config is not valid`, waitForAsync(() => {
- spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
+ it('returns empty array if config is not valid', async () => {
+ vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
of([
{ configId: 'configId1' } as OpenIdConfiguration,
{ configId: 'configId2' } as OpenIdConfiguration,
])
);
- spyOn(configValidationService, 'validateConfigs').and.returnValue(false);
+ vi.spyOn(configValidationService, 'validateConfigs').mockReturnValue(
+ false
+ );
configService
.getOpenIDConfigurations()
@@ -267,12 +279,12 @@ describe('Configuration Service', () => {
expect(allConfigs).toEqual([]);
expect(currentConfig).toBeNull();
});
- }));
+ });
});
describe('setSpecialCases', () => {
- it(`should set special cases when current platform is browser`, () => {
- spyOn(platformProvider, 'isBrowser').and.returnValue(false);
+ it('should set special cases when current platform is browser', () => {
+ vi.spyOn(platformProvider, 'isBrowser').mockReturnValue(false);
const config = { configId: 'configId1' } as OpenIdConfiguration;
diff --git a/src/config/config.service.ts b/src/config/config.service.ts
index c7526c4..80ce2ab 100644
--- a/src/config/config.service.ts
+++ b/src/config/config.service.ts
@@ -1,6 +1,7 @@
-import {inject, Injectable, isDevMode} from 'injection-js';
-import { forkJoin, Observable, of } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, forkJoin, of } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
+import { injectAbstractType } from '../injection/inject';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
@@ -9,7 +10,7 @@ import { PlatformProvider } from '../utils/platform-provider/platform.provider';
import { AuthWellKnownService } from './auth-well-known/auth-well-known.service';
import { DEFAULT_CONFIG } from './default-config';
import { StsConfigLoader } from './loader/config-loader';
-import { OpenIdConfiguration } from './openid-configuration';
+import type { OpenIdConfiguration } from './openid-configuration';
import { ConfigValidationService } from './validation/config-validation.service';
@Injectable()
@@ -26,7 +27,7 @@ export class ConfigurationService {
private readonly authWellKnownService = inject(AuthWellKnownService);
- private readonly loader = inject(StsConfigLoader);
+ private readonly loader = injectAbstractType(StsConfigLoader);
private readonly configValidationService = inject(ConfigValidationService);
@@ -84,11 +85,14 @@ export class ConfigurationService {
}
private getConfig(configId?: string): OpenIdConfiguration | null {
- if (Boolean(configId)) {
+ if (configId) {
const config = this.configsInternal[configId!];
- if(!config && isDevMode()) {
- console.warn(`[oidc-client-rx] No configuration found for config id '${configId}'.`);
+ if (!config) {
+ // biome-ignore lint/suspicious/noConsole:
+ console.warn(
+ `[oidc-client-rx] No configuration found for config id '${configId}'.`
+ );
}
return config || null;
@@ -165,7 +169,7 @@ export class ConfigurationService {
configuration
);
- if (!!alreadyExistingAuthWellKnownEndpoints) {
+ if (alreadyExistingAuthWellKnownEndpoints) {
configuration.authWellknownEndpoints =
alreadyExistingAuthWellKnownEndpoints;
@@ -174,7 +178,7 @@ export class ConfigurationService {
const passedAuthWellKnownEndpoints = configuration.authWellknownEndpoints;
- if (!!passedAuthWellKnownEndpoints) {
+ if (passedAuthWellKnownEndpoints) {
this.authWellKnownService.storeWellKnownEndpoints(
configuration,
passedAuthWellKnownEndpoints
diff --git a/src/config/loader/config-loader.spec.ts b/src/config/loader/config-loader.spec.ts
index 3ee4514..dc1b069 100644
--- a/src/config/loader/config-loader.spec.ts
+++ b/src/config/loader/config-loader.spec.ts
@@ -1,12 +1,12 @@
-import { waitForAsync } from '@angular/core/testing';
+import { waitForAsync } from '@/testing';
import { of } from 'rxjs';
-import { OpenIdConfiguration } from '../openid-configuration';
+import type { OpenIdConfiguration } from '../openid-configuration';
import { StsConfigHttpLoader, StsConfigStaticLoader } from './config-loader';
describe('ConfigLoader', () => {
describe('StsConfigStaticLoader', () => {
describe('loadConfigs', () => {
- it('returns an array if an array is passed', waitForAsync(() => {
+ it('returns an array if an array is passed', async () => {
const toPass = [
{ configId: 'configId1' } as OpenIdConfiguration,
{ configId: 'configId2' } as OpenIdConfiguration,
@@ -17,11 +17,11 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs();
result$.subscribe((result) => {
- expect(Array.isArray(result)).toBeTrue();
+ expect(Array.isArray(result)).toBeTruthy();
});
- }));
+ });
- it('returns an array if only one config is passed', waitForAsync(() => {
+ it('returns an array if only one config is passed', async () => {
const loader = new StsConfigStaticLoader({
configId: 'configId1',
} as OpenIdConfiguration);
@@ -29,15 +29,15 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs();
result$.subscribe((result) => {
- expect(Array.isArray(result)).toBeTrue();
+ expect(Array.isArray(result)).toBeTruthy();
});
- }));
+ });
});
});
describe('StsConfigHttpLoader', () => {
describe('loadConfigs', () => {
- it('returns an array if an array of observables is passed', waitForAsync(() => {
+ it('returns an array if an array of observables is passed', async () => {
const toPass = [
of({ configId: 'configId1' } as OpenIdConfiguration),
of({ configId: 'configId2' } as OpenIdConfiguration),
@@ -47,13 +47,13 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs();
result$.subscribe((result) => {
- expect(Array.isArray(result)).toBeTrue();
+ expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1');
expect(result[1].configId).toBe('configId2');
});
- }));
+ });
- it('returns an array if an observable with a config array is passed', waitForAsync(() => {
+ it('returns an array if an observable with a config array is passed', async () => {
const toPass = of([
{ configId: 'configId1' } as OpenIdConfiguration,
{ configId: 'configId2' } as OpenIdConfiguration,
@@ -63,13 +63,13 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs();
result$.subscribe((result) => {
- expect(Array.isArray(result)).toBeTrue();
+ expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1');
expect(result[1].configId).toBe('configId2');
});
- }));
+ });
- it('returns an array if only one config is passed', waitForAsync(() => {
+ it('returns an array if only one config is passed', async () => {
const loader = new StsConfigHttpLoader(
of({ configId: 'configId1' } as OpenIdConfiguration)
);
@@ -77,10 +77,10 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs();
result$.subscribe((result) => {
- expect(Array.isArray(result)).toBeTrue();
+ expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1');
});
- }));
+ });
});
});
});
diff --git a/src/config/loader/config-loader.ts b/src/config/loader/config-loader.ts
index 0dba6b9..6e4d190 100644
--- a/src/config/loader/config-loader.ts
+++ b/src/config/loader/config-loader.ts
@@ -1,7 +1,7 @@
-import { Provider } from 'injection-js';
-import { forkJoin, Observable, of } from 'rxjs';
+import type { Provider } from 'injection-js';
+import { type Observable, forkJoin, of } from 'rxjs';
import { map } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../openid-configuration';
+import type { OpenIdConfiguration } from '../openid-configuration';
export class OpenIdConfigLoader {
loader?: Provider;
@@ -13,6 +13,7 @@ export abstract class StsConfigLoader {
export class StsConfigStaticLoader implements StsConfigLoader {
constructor(
+ // biome-ignore lint/style/noParameterProperties:
private readonly passedConfigs: OpenIdConfiguration | OpenIdConfiguration[]
) {}
@@ -27,6 +28,7 @@ export class StsConfigStaticLoader implements StsConfigLoader {
export class StsConfigHttpLoader implements StsConfigLoader {
constructor(
+ // biome-ignore lint/style/noParameterProperties:
private readonly configs$:
| Observable
| Observable[]
diff --git a/src/config/openid-configuration.ts b/src/config/openid-configuration.ts
index 3dd95ab..b1bb650 100644
--- a/src/config/openid-configuration.ts
+++ b/src/config/openid-configuration.ts
@@ -1,5 +1,5 @@
-import { LogLevel } from '../logging/log-level';
-import { AuthWellKnownEndpoints } from './auth-well-known/auth-well-known-endpoints';
+import type { LogLevel } from '../logging/log-level';
+import type { AuthWellKnownEndpoints } from './auth-well-known/auth-well-known-endpoints';
export interface OpenIdConfiguration {
/**
@@ -207,5 +207,5 @@ export interface OpenIdConfiguration {
/**
* Disable cleaning up the popup when receiving invalid messages
*/
- disableCleaningPopupOnInvalidMessage?: boolean
+ disableCleaningPopupOnInvalidMessage?: boolean;
}
diff --git a/src/config/validation/config-validation.service.spec.ts b/src/config/validation/config-validation.service.spec.ts
index 7bf529f..a6e2953 100644
--- a/src/config/validation/config-validation.service.spec.ts
+++ b/src/config/validation/config-validation.service.spec.ts
@@ -1,8 +1,9 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
+import { vi } from 'vitest';
import { LogLevel } from '../../logging/log-level';
import { LoggerService } from '../../logging/logger.service';
-import { OpenIdConfiguration } from '../openid-configuration';
+import { mockProvider } from '../../testing/mock';
+import type { OpenIdConfiguration } from '../openid-configuration';
import { ConfigValidationService } from './config-validation.service';
import { allMultipleConfigRules } from './rules';
@@ -14,6 +15,8 @@ describe('Config Validation Service', () => {
TestBed.configureTestingModule({
providers: [ConfigValidationService, mockProvider(LoggerService)],
});
+ configValidationService = TestBed.inject(ConfigValidationService);
+ loggerService = TestBed.inject(LoggerService);
});
const VALID_CONFIG = {
@@ -29,11 +32,6 @@ describe('Config Validation Service', () => {
logLevel: LogLevel.Debug,
};
- beforeEach(() => {
- configValidationService = TestBed.inject(ConfigValidationService);
- loggerService = TestBed.inject(LoggerService);
- });
-
it('should create', () => {
expect(configValidationService).toBeTruthy();
});
@@ -42,26 +40,27 @@ describe('Config Validation Service', () => {
const config = {};
const result = configValidationService.validateConfig(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('should return true for valid config', () => {
const result = configValidationService.validateConfig(VALID_CONFIG);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('calls `logWarning` if one rule has warning level', () => {
- const loggerWarningSpy = spyOn(loggerService, 'logWarning');
- const messageTypeSpy = spyOn(
+ const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
+ const messageTypeSpy = vi.spyOn(
configValidationService as any,
'getAllMessagesOfType'
);
- messageTypeSpy
- .withArgs('warning', jasmine.any(Array))
- .and.returnValue(['A warning message']);
- messageTypeSpy.withArgs('error', jasmine.any(Array)).and.callThrough();
+ mockImplementationWhenArgsEqual(
+ messageTypeSpy,
+ (arg1: any, arg2: any) => arg1 === 'warning' && Array.isArray(arg2),
+ () => ['A warning message']
+ );
configValidationService.validateConfig(VALID_CONFIG);
expect(loggerWarningSpy).toHaveBeenCalled();
@@ -72,7 +71,7 @@ describe('Config Validation Service', () => {
const config = { ...VALID_CONFIG, clientId: '' } as OpenIdConfiguration;
const result = configValidationService.validateConfig(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
});
@@ -84,7 +83,7 @@ describe('Config Validation Service', () => {
} as OpenIdConfiguration;
const result = configValidationService.validateConfig(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
});
@@ -93,7 +92,7 @@ describe('Config Validation Service', () => {
const config = { ...VALID_CONFIG, redirectUrl: '' };
const result = configValidationService.validateConfig(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
});
@@ -107,7 +106,7 @@ describe('Config Validation Service', () => {
} as OpenIdConfiguration;
const result = configValidationService.validateConfig(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
});
@@ -120,12 +119,12 @@ describe('Config Validation Service', () => {
scopes: 'scope1 scope2 but_no_offline_access',
};
- const loggerSpy = spyOn(loggerService, 'logError');
- const loggerWarningSpy = spyOn(loggerService, 'logWarning');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
+ const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
const result = configValidationService.validateConfig(config);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
expect(loggerSpy).not.toHaveBeenCalled();
expect(loggerWarningSpy).toHaveBeenCalled();
});
@@ -146,47 +145,47 @@ describe('Config Validation Service', () => {
scopes: 'scope1 scope2 but_no_offline_access',
};
- const loggerErrorSpy = spyOn(loggerService, 'logError');
- const loggerWarningSpy = spyOn(loggerService, 'logWarning');
+ const loggerErrorSpy = vi.spyOn(loggerService, 'logError');
+ const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
const result = configValidationService.validateConfigs([
config1,
config2,
]);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
expect(loggerErrorSpy).not.toHaveBeenCalled();
- expect(loggerWarningSpy.calls.argsFor(0)).toEqual([
+ expect(vi.mocked(loggerWarningSpy).mock.calls[0]).toEqual([
config1,
'You added multiple configs with the same authority, clientId and scope',
]);
- expect(loggerWarningSpy.calls.argsFor(1)).toEqual([
+ expect(vi.mocked(loggerWarningSpy).mock.calls[1]).toEqual([
config2,
'You added multiple configs with the same authority, clientId and scope',
]);
});
it('should return false and a better error message when config is not passed as object with config property', () => {
- const loggerWarningSpy = spyOn(loggerService, 'logWarning');
+ const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
const result = configValidationService.validateConfigs([]);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
expect(loggerWarningSpy).not.toHaveBeenCalled();
});
});
describe('validateConfigs', () => {
it('calls internal method with empty array if something falsy is passed', () => {
- const spy = spyOn(
+ const spy = vi.spyOn(
configValidationService as any,
'validateConfigsInternal'
- ).and.callThrough();
+ );
const result = configValidationService.validateConfigs([]);
- expect(result).toBeFalse();
- expect(spy).toHaveBeenCalledOnceWith([], allMultipleConfigRules);
+ expect(result).toBeFalsy();
+ expect(spy).toHaveBeenCalledExactlyOnceWith([], allMultipleConfigRules);
});
});
});
diff --git a/src/extractors/jwk.extractor.spec.ts b/src/extractors/jwk.extractor.spec.ts
index 31fbdc1..e4e9db6 100644
--- a/src/extractors/jwk.extractor.spec.ts
+++ b/src/extractors/jwk.extractor.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { CryptoService } from '../utils/crypto/crypto.service';
import {
JwkExtractor,
diff --git a/src/flows/callback-handling/code-flow-callback-handler.service.spec.ts b/src/flows/callback-handling/code-flow-callback-handler.service.spec.ts
index d8a8108..2c5f362 100644
--- a/src/flows/callback-handling/code-flow-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/code-flow-callback-handler.service.spec.ts
@@ -1,14 +1,15 @@
-import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
+import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
-import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
+import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
+import { mockProvider } from '../../testing/mock';
import { UrlService } from '../../utils/url/url.service';
import { TokenValidationService } from '../../validation/token-validation.service';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { CodeFlowCallbackHandlerService } from './code-flow-callback-handler.service';
@@ -46,13 +47,16 @@ describe('CodeFlowCallbackHandlerService', () => {
});
describe('codeFlowCallback', () => {
- it('throws error if no state is given', waitForAsync(() => {
- const getUrlParameterSpy = spyOn(
- urlService,
- 'getUrlParameter'
- ).and.returnValue('params');
+ it('throws error if no state is given', async () => {
+ const getUrlParameterSpy = vi
+ .spyOn(urlService, 'getUrlParameter')
+ .mockReturnValue('params');
- getUrlParameterSpy.withArgs('test-url', 'state').and.returnValue('');
+ mockImplementationWhenArgsEqual(
+ getUrlParameterSpy,
+ ['test-url', 'state'],
+ () => ''
+ );
service
.codeFlowCallback('test-url', { configId: 'configId1' })
@@ -61,15 +65,14 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('throws error if no code is given', waitForAsync(() => {
- const getUrlParameterSpy = spyOn(
- urlService,
- 'getUrlParameter'
- ).and.returnValue('params');
+ it('throws error if no code is given', async () => {
+ const getUrlParameterSpy = vi
+ .spyOn(urlService, 'getUrlParameter')
+ .mockReturnValue('params');
- getUrlParameterSpy.withArgs('test-url', 'code').and.returnValue('');
+ getUrlParameterSpy.withArgs('test-url', 'code').mockReturnValue('');
service
.codeFlowCallback('test-url', { configId: 'configId1' })
@@ -78,10 +81,10 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('returns callbackContext if all params are good', waitForAsync(() => {
- spyOn(urlService, 'getUrlParameter').and.returnValue('params');
+ it('returns callbackContext if all params are good', async () => {
+ vi.spyOn(urlService, 'getUrlParameter').mockReturnValue('params');
const expectedCallbackContext = {
code: 'params',
@@ -100,7 +103,7 @@ describe('CodeFlowCallbackHandlerService', () => {
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext);
});
- }));
+ });
});
describe('codeFlowCodeRequest ', () => {
@@ -112,11 +115,11 @@ describe('CodeFlowCallbackHandlerService', () => {
url: 'https://identity-server.test/openid-connect/token',
});
- it('throws error if state is not correct', waitForAsync(() => {
- spyOn(
+ it('throws error if state is not correct', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
@@ -125,16 +128,18 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('throws error if authWellknownEndpoints is null is given', waitForAsync(() => {
- spyOn(
+ it('throws error if authWellknownEndpoints is null is given', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue(null);
+ ).mockReturnValue(true);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => null
+ );
service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
@@ -143,16 +148,18 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('throws error if tokenendpoint is null is given', waitForAsync(() => {
- spyOn(
+ it('throws error if tokenendpoint is null is given', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ tokenEndpoint: null });
+ ).mockReturnValue(true);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ tokenEndpoint: null })
+ );
service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
@@ -161,34 +168,36 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('calls dataService if all params are good', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ it('calls dataService if all params are good', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
.subscribe(() => {
- expect(postSpy).toHaveBeenCalledOnceWith(
+ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint',
undefined,
{ configId: 'configId1' },
- jasmine.any(HttpHeaders)
+ expect.any(HttpHeaders)
);
});
- }));
+ });
- it('calls url service with custom token params', waitForAsync(() => {
- const urlServiceSpy = spyOn(
+ it('calls url service with custom token params', async () => {
+ const urlServiceSpy = vi.spyOn(
urlService,
'createBodyForCodeFlowCodeRequest'
);
@@ -197,76 +206,84 @@ describe('CodeFlowCallbackHandlerService', () => {
customParamsCodeRequest: { foo: 'bar' },
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
- const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
service
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config)
.subscribe(() => {
- expect(urlServiceSpy).toHaveBeenCalledOnceWith('foo', config, {
+ expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
foo: 'bar',
});
expect(postSpy).toHaveBeenCalledTimes(1);
});
- }));
+ });
- it('calls dataService with correct headers if all params are good', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ it('calls dataService with correct headers if all params are good', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
const config = {
configId: 'configId1',
customParamsCodeRequest: { foo: 'bar' },
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
service
.codeFlowCodeRequest({} as CallbackContext, config)
.subscribe(() => {
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
- expect(httpHeaders.has('Content-Type')).toBeTrue();
+ expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded'
);
});
- }));
+ });
- it('returns error in case of http error', waitForAsync(() => {
- spyOn(dataService, 'post').and.returnValue(throwError(() => HTTP_ERROR));
+ it('returns error in case of http error', async () => {
+ vi.spyOn(dataService, 'post').mockReturnValue(
+ throwError(() => HTTP_ERROR)
+ );
const config = {
configId: 'configId1',
customParamsCodeRequest: { foo: 'bar' },
authority: 'authority',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
error: (err) => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('retries request in case of no connection http error and succeeds', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(
+ it('retries request in case of no connection http error and succeeds', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => CONNECTION_ERROR),
of({})
@@ -278,14 +295,16 @@ describe('CodeFlowCallbackHandlerService', () => {
authority: 'authority',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
next: (res) => {
@@ -297,10 +316,10 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(err).toBeFalsy();
},
});
- }));
+ });
- it('retries request in case of no connection http error and fails because of http error afterwards', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(
+ it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => CONNECTION_ERROR),
throwError(() => HTTP_ERROR)
@@ -312,14 +331,16 @@ describe('CodeFlowCallbackHandlerService', () => {
authority: 'authority',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
next: (res) => {
@@ -331,6 +352,6 @@ describe('CodeFlowCallbackHandlerService', () => {
expect(postSpy).toHaveBeenCalledTimes(1);
},
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/error-helper.spec.ts b/src/flows/callback-handling/error-helper.spec.ts
index 7c7f16d..54f2409 100644
--- a/src/flows/callback-handling/error-helper.spec.ts
+++ b/src/flows/callback-handling/error-helper.spec.ts
@@ -1,4 +1,4 @@
-import { HttpErrorResponse } from '@angular/common/http';
+import { HttpErrorResponse } from '@ngify/http';
import { isNetworkError } from './error-helper';
describe('error helper', () => {
@@ -27,31 +27,31 @@ describe('error helper', () => {
});
it('returns true on http error with status = 0', () => {
- expect(isNetworkError(CONNECTION_ERROR)).toBeTrue();
+ expect(isNetworkError(CONNECTION_ERROR)).toBeTruthy();
});
it('returns true on http error with status = 0 and unknown error', () => {
- expect(isNetworkError(UNKNOWN_CONNECTION_ERROR)).toBeTrue();
+ expect(isNetworkError(UNKNOWN_CONNECTION_ERROR)).toBeTruthy();
});
it('returns true on http error with status <> 0 and error ProgressEvent', () => {
- expect(isNetworkError(PARTIAL_CONNECTION_ERROR)).toBeTrue();
+ expect(isNetworkError(PARTIAL_CONNECTION_ERROR)).toBeTruthy();
});
it('returns false on non http error', () => {
- expect(isNetworkError(new Error('not a HttpErrorResponse'))).toBeFalse();
+ expect(isNetworkError(new Error('not a HttpErrorResponse'))).toBeFalsy();
});
it('returns false on string error', () => {
- expect(isNetworkError('not a HttpErrorResponse')).toBeFalse();
+ expect(isNetworkError('not a HttpErrorResponse')).toBeFalsy();
});
it('returns false on undefined', () => {
- expect(isNetworkError(undefined)).toBeFalse();
+ expect(isNetworkError(undefined)).toBeFalsy();
});
it('returns false on empty http error', () => {
- expect(isNetworkError(HTTP_ERROR)).toBeFalse();
+ expect(isNetworkError(HTTP_ERROR)).toBeFalsy();
});
});
});
diff --git a/src/flows/callback-handling/history-jwt-keys-callback-handler.service.spec.ts b/src/flows/callback-handling/history-jwt-keys-callback-handler.service.spec.ts
index 754420c..dd65080 100644
--- a/src/flows/callback-handling/history-jwt-keys-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/history-jwt-keys-callback-handler.service.spec.ts
@@ -1,12 +1,13 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../../auth-state/auth-state.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
-import { JwtKey, JwtKeys } from '../../validation/jwtkeys';
+import { mockProvider } from '../../testing/mock';
+import type { JwtKey, JwtKeys } from '../../validation/jwtkeys';
import { ValidationResult } from '../../validation/validation-result';
-import { AuthResult, CallbackContext } from '../callback-context';
+import type { AuthResult, CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
import { SigninKeyDataService } from '../signin-key-data.service';
@@ -46,9 +47,6 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
mockProvider(ResetAuthDataService),
],
});
- });
-
- beforeEach(() => {
service = TestBed.inject(HistoryJwtKeysCallbackHandlerService);
storagePersistenceService = TestBed.inject(StoragePersistenceService);
resetAuthDataService = TestBed.inject(ResetAuthDataService);
@@ -62,8 +60,8 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
});
describe('callbackHistoryAndResetJwtKeys', () => {
- it('writes authResult into the storage', waitForAsync(() => {
- const storagePersistenceServiceSpy = spyOn(
+ it('writes authResult into the storage', async () => {
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
@@ -75,86 +73,86 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
const callbackContext = {
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe(() => {
- expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
- ['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
- ['jwtKeys', { keys: [] }, allconfigs[0]],
+ expect(storagePersistenceServiceSpy).toBeCalledWith([
+ ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
+ ['jwtKeys', { keys: [] }, allConfigs[0]],
]);
// write authnResult & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
});
- }));
+ });
- it('writes refresh_token into the storage without reuse (refresh token rotation)', waitForAsync(() => {
+ it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => {
const DUMMY_AUTH_RESULT = {
refresh_token: 'dummy_refresh_token',
id_token: 'some-id-token',
};
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
const callbackContext = {
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe(() => {
- expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
- ['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
- ['jwtKeys', { keys: [] }, allconfigs[0]],
+ expect(storagePersistenceServiceSpy).toBeCalledWith([
+ ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
+ ['jwtKeys', { keys: [] }, allConfigs[0]],
]);
// write authnResult & refresh_token & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
});
- }));
+ });
- it('writes refresh_token into the storage with reuse (without refresh token rotation)', waitForAsync(() => {
+ it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => {
const DUMMY_AUTH_RESULT = {
refresh_token: 'dummy_refresh_token',
id_token: 'some-id-token',
};
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
const callbackContext = {
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
@@ -162,27 +160,27 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe(() => {
- expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
- ['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
- ['reusable_refresh_token', 'dummy_refresh_token', allconfigs[0]],
- ['jwtKeys', { keys: [] }, allconfigs[0]],
+ expect(storagePersistenceServiceSpy).toBeCalledWith([
+ ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
+ ['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
+ ['jwtKeys', { keys: [] }, allConfigs[0]],
]);
// write authnResult & refresh_token & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
});
- }));
+ });
- it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', waitForAsync(() => {
+ it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => {
const DUMMY_AUTH_RESULT = {
id_token: 'some-id-token',
};
@@ -190,30 +188,30 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
isRenewProcess: false,
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: false,
},
];
- const windowSpy = spyOn(window.history, 'replaceState');
+ const windowSpy = vi.spyOn(window.history, 'replaceState');
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe(() => {
expect(windowSpy).toHaveBeenCalledTimes(1);
});
- }));
+ });
- it('returns callbackContext with jwtkeys filled if everything works fine', waitForAsync(() => {
+ it('returns callbackContext with jwtkeys filled if everything works fine', async () => {
const DUMMY_AUTH_RESULT = {
id_token: 'some-id-token',
};
@@ -222,21 +220,21 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
isRenewProcess: false,
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: false,
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe((result) => {
expect(result).toEqual({
@@ -245,9 +243,9 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
jwtKeys: { keys: [{ kty: 'henlo' }] },
} as CallbackContext);
});
- }));
+ });
- it('returns error if no jwtKeys have been in the call --> keys are null', waitForAsync(() => {
+ it('returns error if no jwtKeys have been in the call --> keys are null', async () => {
const DUMMY_AUTH_RESULT = {
id_token: 'some-id-token',
};
@@ -256,32 +254,32 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
isRenewProcess: false,
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: false,
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({} as JwtKeys)
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
error: (err) => {
expect(err.message).toEqual(
- `Failed to retrieve signing key with error: Error: Failed to retrieve signing key`
+ 'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
);
},
});
- }));
+ });
- it('returns error if no jwtKeys have been in the call --> keys throw an error', waitForAsync(() => {
+ it('returns error if no jwtKeys have been in the call --> keys throw an error', async () => {
const DUMMY_AUTH_RESULT = {
id_token: 'some-id-token',
};
@@ -289,36 +287,36 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
isRenewProcess: false,
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: false,
},
];
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
throwError(() => new Error('error'))
);
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
error: (err) => {
expect(err.message).toEqual(
- `Failed to retrieve signing key with error: Error: Error: error`
+ 'Failed to retrieve signing key with error: Error: Error: error'
);
},
});
- }));
+ });
- it('returns error if callbackContext.authresult has an error property filled', waitForAsync(() => {
+ it('returns error if callbackContext.authresult has an error property filled', async () => {
const callbackContext = {
authResult: { error: 'someError' },
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
@@ -328,36 +326,36 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
error: (err) => {
expect(err.message).toEqual(
- `AuthCallback AuthResult came with error: someError`
+ 'AuthCallback AuthResult came with error: someError'
);
},
});
- }));
+ });
- it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', waitForAsync(() => {
+ it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', async () => {
const callbackContext = {
authResult: { error: 'someError' },
isRenewProcess: false,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const setNonceSpy = spyOn(flowsDataService, 'setNonce');
- const updateAndPublishAuthStateSpy = spyOn(
+ const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
@@ -365,40 +363,42 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
error: () => {
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
expect(setNonceSpy).toHaveBeenCalledTimes(1);
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(
+ updateAndPublishAuthStateSpy
+ ).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
validationResult: ValidationResult.SecureTokenServerError,
isRenewProcess: false,
});
},
});
- }));
+ });
- it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', waitForAsync(() => {
+ it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', async () => {
const callbackContext = {
authResult: { error: 'login_required' },
isRenewProcess: false,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const setNonceSpy = spyOn(flowsDataService, 'setNonce');
- const updateAndPublishAuthStateSpy = spyOn(
+ const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
@@ -406,23 +406,25 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
service
.callbackHistoryAndResetJwtKeys(
callbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
error: () => {
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
expect(setNonceSpy).toHaveBeenCalledTimes(1);
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(
+ updateAndPublishAuthStateSpy
+ ).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
validationResult: ValidationResult.LoginRequired,
isRenewProcess: false,
});
},
});
- }));
+ });
- it('should store jwtKeys', waitForAsync(() => {
+ it('should store jwtKeys', async () => {
const DUMMY_AUTH_RESULT = {
id_token: 'some-id-token',
};
@@ -430,33 +432,33 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
const initialCallbackContext = {
authResult: DUMMY_AUTH_RESULT,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of(DUMMY_JWT_KEYS)
);
service
.callbackHistoryAndResetJwtKeys(
initialCallbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
next: (callbackContext: CallbackContext) => {
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
- expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
- ['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
- ['jwtKeys', DUMMY_JWT_KEYS, allconfigs[0]],
+ expect(storagePersistenceServiceSpy).toBeCalledWith([
+ ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
+ ['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
]);
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
@@ -465,9 +467,9 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
expect(err).toBeFalsy();
},
});
- }));
+ });
- it('should not store jwtKeys on error', waitForAsync(() => {
+ it('should not store jwtKeys on error', async () => {
const authResult = {
id_token: 'some-id-token',
access_token: 'some-access-token',
@@ -476,26 +478,26 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
authResult,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
throwError(() => new Error('Error'))
);
service
.callbackHistoryAndResetJwtKeys(
initialCallbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
next: (callbackContext: CallbackContext) => {
@@ -505,16 +507,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
expect(err).toBeTruthy();
// storagePersistenceService.write() should not have been called with jwtKeys
- expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
+ expect(
+ storagePersistenceServiceSpy
+ ).toHaveBeenCalledExactlyOnceWith(
'authnResult',
authResult,
- allconfigs[0]
+ allConfigs[0]
);
},
});
- }));
+ });
- it('should fallback to stored jwtKeys on error', waitForAsync(() => {
+ it('should fallback to stored jwtKeys on error', async () => {
const authResult = {
id_token: 'some-id-token',
access_token: 'some-access-token',
@@ -523,66 +527,65 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
authResult,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'read'
);
- storagePersistenceServiceSpy.and.returnValue(DUMMY_JWT_KEYS);
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ storagePersistenceServiceSpy.mockReturnValue(DUMMY_JWT_KEYS);
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
throwError(() => new Error('Error'))
);
service
.callbackHistoryAndResetJwtKeys(
initialCallbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
next: (callbackContext: CallbackContext) => {
- expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
- 'jwtKeys',
- allconfigs[0]
- );
+ expect(
+ storagePersistenceServiceSpy
+ ).toHaveBeenCalledExactlyOnceWith('jwtKeys', allConfigs[0]);
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
},
error: (err) => {
expect(err).toBeFalsy();
},
});
- }));
+ });
- it('should throw error if no jwtKeys are stored', waitForAsync(() => {
+ it('should throw error if no jwtKeys are stored', async () => {
const authResult = {
id_token: 'some-id-token',
access_token: 'some-access-token',
} as AuthResult;
const initialCallbackContext = { authResult } as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
historyCleanupOff: true,
},
];
- spyOn(storagePersistenceService, 'read').and.returnValue(null);
- spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);
+ vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
throwError(() => new Error('Error'))
);
service
.callbackHistoryAndResetJwtKeys(
initialCallbackContext,
- allconfigs[0],
- allconfigs
+ allConfigs[0]!,
+ allConfigs
)
.subscribe({
next: (callbackContext: CallbackContext) => {
@@ -592,7 +595,7 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
describe('historyCleanUpTurnedOn ', () => {
diff --git a/src/flows/callback-handling/history-jwt-keys-callback-handler.service.ts b/src/flows/callback-handling/history-jwt-keys-callback-handler.service.ts
index 5dba20f..3e826df 100644
--- a/src/flows/callback-handling/history-jwt-keys-callback-handler.service.ts
+++ b/src/flows/callback-handling/history-jwt-keys-callback-handler.service.ts
@@ -1,14 +1,14 @@
-import { DOCUMENT } from '../../dom';
-import { inject, Injectable } from 'injection-js';
-import { Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of, throwError } from 'rxjs';
import { catchError, switchMap, tap } from 'rxjs/operators';
import { AuthStateService } from '../../auth-state/auth-state.service';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
+import { DOCUMENT } from '../../dom';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
-import { JwtKeys } from '../../validation/jwtkeys';
+import type { JwtKeys } from '../../validation/jwtkeys';
import { ValidationResult } from '../../validation/validation-result';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
import { SigninKeyDataService } from '../signin-key-data.service';
diff --git a/src/flows/callback-handling/implicit-flow-callback-handler.service.spec.ts b/src/flows/callback-handling/implicit-flow-callback-handler.service.spec.ts
index 1feec31..8120d0f 100644
--- a/src/flows/callback-handling/implicit-flow-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/implicit-flow-callback-handler.service.spec.ts
@@ -1,8 +1,9 @@
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DOCUMENT } from '../../dom';
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
import { LoggerService } from '../../logging/logger.service';
-import { CallbackContext } from '../callback-context';
+import { mockProvider } from '../../testing/mock';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
import { ImplicitFlowCallbackHandlerService } from './implicit-flow-callback-handler.service';
@@ -34,9 +35,6 @@ describe('ImplicitFlowCallbackHandlerService', () => {
},
],
});
- });
-
- beforeEach(() => {
service = TestBed.inject(ImplicitFlowCallbackHandlerService);
flowsDataService = TestBed.inject(FlowsDataService);
resetAuthDataService = TestBed.inject(ResetAuthDataService);
@@ -47,46 +45,46 @@ describe('ImplicitFlowCallbackHandlerService', () => {
});
describe('implicitFlowCallback', () => {
- it('calls "resetAuthorizationData" if silent renew is not running', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
- const resetAuthorizationDataSpy = spyOn(
+ it('calls "resetAuthorizationData" if silent renew is not running', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
},
];
service
- .implicitFlowCallback(allconfigs[0], allconfigs, 'any-hash')
+ .implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
.subscribe(() => {
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
});
- }));
+ });
- it('does NOT calls "resetAuthorizationData" if silent renew is running', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
- const resetAuthorizationDataSpy = spyOn(
+ it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
},
];
service
- .implicitFlowCallback(allconfigs[0], allconfigs, 'any-hash')
+ .implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
.subscribe(() => {
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('returns callbackContext if all params are good', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ it('returns callbackContext if all params are good', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
const expectedCallbackContext = {
code: '',
refreshToken: '',
@@ -99,21 +97,21 @@ describe('ImplicitFlowCallbackHandlerService', () => {
existingIdToken: null,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
},
];
service
- .implicitFlowCallback(allconfigs[0], allconfigs, 'anyHash')
+ .implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash')
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext);
});
- }));
+ });
- it('uses window location hash if no hash is passed', waitForAsync(() => {
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ it('uses window location hash if no hash is passed', async () => {
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
const expectedCallbackContext = {
code: '',
refreshToken: '',
@@ -126,17 +124,17 @@ describe('ImplicitFlowCallbackHandlerService', () => {
existingIdToken: null,
} as CallbackContext;
- const allconfigs = [
+ const allConfigs = [
{
configId: 'configId1',
},
];
service
- .implicitFlowCallback(allconfigs[0], allconfigs)
+ .implicitFlowCallback(allConfigs[0]!, allConfigs)
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext);
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/implicit-flow-callback-handler.service.ts b/src/flows/callback-handling/implicit-flow-callback-handler.service.ts
index a676f0d..16097d1 100644
--- a/src/flows/callback-handling/implicit-flow-callback-handler.service.ts
+++ b/src/flows/callback-handling/implicit-flow-callback-handler.service.ts
@@ -1,9 +1,9 @@
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of } from 'rxjs';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { DOCUMENT } from '../../dom';
-import { inject, Injectable } from 'injection-js';
-import { Observable, of } from 'rxjs';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
import { LoggerService } from '../../logging/logger.service';
-import { AuthResult, CallbackContext } from '../callback-context';
+import type { AuthResult, CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
diff --git a/src/flows/callback-handling/refresh-session-callback-handler.service.spec.ts b/src/flows/callback-handling/refresh-session-callback-handler.service.spec.ts
index 9973dc3..3c7553e 100644
--- a/src/flows/callback-handling/refresh-session-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/refresh-session-callback-handler.service.spec.ts
@@ -1,8 +1,9 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { AuthStateService } from '../../auth-state/auth-state.service';
import { LoggerService } from '../../logging/logger.service';
-import { CallbackContext } from '../callback-context';
+import { mockProvider } from '../../testing/mock';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { RefreshSessionCallbackHandlerService } from './refresh-session-callback-handler.service';
@@ -33,15 +34,15 @@ describe('RefreshSessionCallbackHandlerService', () => {
});
describe('refreshSessionWithRefreshTokens', () => {
- it('returns callbackContext if all params are good', waitForAsync(() => {
- spyOn(
+ it('returns callbackContext if all params are good', async () => {
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('state-data');
- spyOn(authStateService, 'getRefreshToken').and.returnValue(
+ ).mockReturnValue('state-data');
+ vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue(
'henlo-furiend'
);
- spyOn(authStateService, 'getIdToken').and.returnValue('henlo-legger');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
const expectedCallbackContext = {
code: '',
@@ -60,15 +61,15 @@ describe('RefreshSessionCallbackHandlerService', () => {
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext);
});
- }));
+ });
- it('throws error if no refresh token is given', waitForAsync(() => {
- spyOn(
+ it('throws error if no refresh token is given', async () => {
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('state-data');
- spyOn(authStateService, 'getRefreshToken').and.returnValue('');
- spyOn(authStateService, 'getIdToken').and.returnValue('henlo-legger');
+ ).mockReturnValue('state-data');
+ vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue('');
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
service
.refreshSessionWithRefreshTokens({ configId: 'configId1' })
@@ -77,6 +78,6 @@ describe('RefreshSessionCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/refresh-token-callback-handler.service.spec.ts b/src/flows/callback-handling/refresh-token-callback-handler.service.spec.ts
index dff9ccf..dda12bd 100644
--- a/src/flows/callback-handling/refresh-token-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/refresh-token-callback-handler.service.spec.ts
@@ -1,13 +1,14 @@
-import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
+import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
-import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
+import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
+import { mockProvider } from '../../testing/mock';
import { UrlService } from '../../utils/url/url.service';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { RefreshTokenCallbackHandlerService } from './refresh-token-callback-handler.service';
describe('RefreshTokenCallbackHandlerService', () => {
@@ -46,7 +47,7 @@ describe('RefreshTokenCallbackHandlerService', () => {
url: 'https://identity-server.test/openid-connect/token',
});
- it('throws error if no tokenEndpoint is given', waitForAsync(() => {
+ it('throws error if no tokenEndpoint is given', async () => {
(service as any)
.refreshTokensRequestTokens({} as CallbackContext)
.subscribe({
@@ -54,41 +55,45 @@ describe('RefreshTokenCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('calls data service if all params are good', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ it('calls data service if all params are good', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service
.refreshTokensRequestTokens({} as CallbackContext, {
configId: 'configId1',
})
.subscribe(() => {
- expect(postSpy).toHaveBeenCalledOnceWith(
+ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint',
undefined,
{ configId: 'configId1' },
- jasmine.any(HttpHeaders)
+ expect.any(HttpHeaders)
);
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
- expect(httpHeaders.has('Content-Type')).toBeTrue();
+ expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded'
);
});
- }));
+ });
- it('calls data service with correct headers if all params are good', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ it('calls data service with correct headers if all params are good', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service
.refreshTokensRequestTokens({} as CallbackContext, {
@@ -97,20 +102,24 @@ describe('RefreshTokenCallbackHandlerService', () => {
.subscribe(() => {
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
- expect(httpHeaders.has('Content-Type')).toBeTrue();
+ expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded'
);
});
- }));
+ });
- it('returns error in case of http error', waitForAsync(() => {
- spyOn(dataService, 'post').and.returnValue(throwError(() => HTTP_ERROR));
+ it('returns error in case of http error', async () => {
+ vi.spyOn(dataService, 'post').mockReturnValue(
+ throwError(() => HTTP_ERROR)
+ );
const config = { configId: 'configId1', authority: 'authority' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service
.refreshTokensRequestTokens({} as CallbackContext, config)
@@ -119,10 +128,10 @@ describe('RefreshTokenCallbackHandlerService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('retries request in case of no connection http error and succeeds', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(
+ it('retries request in case of no connection http error and succeeds', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => CONNECTION_ERROR),
of({})
@@ -130,9 +139,11 @@ describe('RefreshTokenCallbackHandlerService', () => {
);
const config = { configId: 'configId1', authority: 'authority' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service
.refreshTokensRequestTokens({} as CallbackContext, config)
@@ -146,10 +157,10 @@ describe('RefreshTokenCallbackHandlerService', () => {
expect(err).toBeFalsy();
},
});
- }));
+ });
- it('retries request in case of no connection http error and fails because of http error afterwards', waitForAsync(() => {
- const postSpy = spyOn(dataService, 'post').and.returnValue(
+ it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => CONNECTION_ERROR),
throwError(() => HTTP_ERROR)
@@ -157,9 +168,11 @@ describe('RefreshTokenCallbackHandlerService', () => {
);
const config = { configId: 'configId1', authority: 'authority' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ tokenEndpoint: 'tokenEndpoint' })
+ );
service
.refreshTokensRequestTokens({} as CallbackContext, config)
@@ -173,6 +186,6 @@ describe('RefreshTokenCallbackHandlerService', () => {
expect(postSpy).toHaveBeenCalledTimes(1);
},
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/state-validation-callback-handler.service.spec.ts b/src/flows/callback-handling/state-validation-callback-handler.service.spec.ts
index 2bd4077..2be057d 100644
--- a/src/flows/callback-handling/state-validation-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/state-validation-callback-handler.service.spec.ts
@@ -1,13 +1,14 @@
-import { DOCUMENT } from '../../dom';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../../auth-state/auth-state.service';
+import { DOCUMENT } from '../../dom';
import { LoggerService } from '../../logging/logger.service';
-import { StateValidationResult } from '../../validation/state-validation-result';
+import { mockProvider } from '../../testing/mock';
+import type { StateValidationResult } from '../../validation/state-validation-result';
import { StateValidationService } from '../../validation/state-validation.service';
import { ValidationResult } from '../../validation/validation-result';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { ResetAuthDataService } from '../reset-auth-data.service';
import { StateValidationCallbackHandlerService } from './state-validation-callback-handler.service';
@@ -56,8 +57,11 @@ describe('StateValidationCallbackHandlerService', () => {
});
describe('callbackStateValidation', () => {
- it('returns callbackContext with validationResult if validationResult is valid', waitForAsync(() => {
- spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
+ it('returns callbackContext with validationResult if validationResult is valid', async () => {
+ vi.spyOn(
+ stateValidationService,
+ 'getValidatedStateResult'
+ ).mockReturnValue(
of({
idToken: 'idTokenJustForTesting',
authResponseIsValid: true,
@@ -68,7 +72,7 @@ describe('StateValidationCallbackHandlerService', () => {
service
.callbackStateValidation(
{} as CallbackContext,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
)
.subscribe((newCallbackContext) => {
@@ -79,47 +83,53 @@ describe('StateValidationCallbackHandlerService', () => {
},
} as CallbackContext);
});
- }));
+ });
- it('logs error in case of an error', waitForAsync(() => {
- spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
+ it('logs error in case of an error', async () => {
+ vi.spyOn(
+ stateValidationService,
+ 'getValidatedStateResult'
+ ).mockReturnValue(
of({
authResponseIsValid: false,
} as StateValidationResult)
);
- const loggerSpy = spyOn(loggerService, 'logWarning');
+ const loggerSpy = vi.spyOn(loggerService, 'logWarning');
const allConfigs = [{ configId: 'configId1' }];
service
.callbackStateValidation(
{} as CallbackContext,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
)
.subscribe({
error: () => {
- expect(loggerSpy).toHaveBeenCalledOnceWith(
- allConfigs[0],
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
+ allConfigs[0]!,
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
);
},
});
- }));
+ });
- it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', waitForAsync(() => {
- spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
+ it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', async () => {
+ vi.spyOn(
+ stateValidationService,
+ 'getValidatedStateResult'
+ ).mockReturnValue(
of({
authResponseIsValid: false,
state: ValidationResult.LoginRequired,
} as StateValidationResult)
);
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const updateAndPublishAuthStateSpy = spyOn(
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
@@ -128,19 +138,21 @@ describe('StateValidationCallbackHandlerService', () => {
service
.callbackStateValidation(
{ isRenewProcess: true } as CallbackContext,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
)
.subscribe({
error: () => {
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(
+ updateAndPublishAuthStateSpy
+ ).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
validationResult: ValidationResult.LoginRequired,
isRenewProcess: true,
});
},
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/state-validation-callback-handler.service.ts b/src/flows/callback-handling/state-validation-callback-handler.service.ts
index bc4c828..8498455 100644
--- a/src/flows/callback-handling/state-validation-callback-handler.service.ts
+++ b/src/flows/callback-handling/state-validation-callback-handler.service.ts
@@ -1,13 +1,13 @@
-import { DOCUMENT } from '../../dom';
-import { inject, Injectable } from 'injection-js';
-import { Observable } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import type { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthStateService } from '../../auth-state/auth-state.service';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
+import { DOCUMENT } from '../../dom';
import { LoggerService } from '../../logging/logger.service';
-import { StateValidationResult } from '../../validation/state-validation-result';
+import type { StateValidationResult } from '../../validation/state-validation-result';
import { StateValidationService } from '../../validation/state-validation.service';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { ResetAuthDataService } from '../reset-auth-data.service';
@Injectable()
diff --git a/src/flows/callback-handling/user-callback-handler.service.spec.ts b/src/flows/callback-handling/user-callback-handler.service.spec.ts
index 5696a6c..b8b464d 100644
--- a/src/flows/callback-handling/user-callback-handler.service.spec.ts
+++ b/src/flows/callback-handling/user-callback-handler.service.spec.ts
@@ -1,12 +1,13 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../../auth-state/auth-state.service';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { UserService } from '../../user-data/user.service';
import { StateValidationResult } from '../../validation/state-validation-result';
import { ValidationResult } from '../../validation/validation-result';
-import { CallbackContext } from '../callback-context';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
import { UserCallbackHandlerService } from './user-callback-handler.service';
@@ -44,7 +45,7 @@ describe('UserCallbackHandlerService', () => {
});
describe('callbackUser', () => {
- it('calls flowsDataService.setSessionState with correct params if autoUserInfo is false, isRenewProcess is false and refreshToken is null', waitForAsync(() => {
+ it('calls flowsDataService.setSessionState with correct params if autoUserInfo is false, isRenewProcess is false and refreshToken is null', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -70,17 +71,17 @@ describe('UserCallbackHandlerService', () => {
},
];
- const spy = spyOn(flowsDataService, 'setSessionState');
+ const spy = vi.spyOn(flowsDataService, 'setSessionState');
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
- expect(spy).toHaveBeenCalledOnceWith('mystate', allConfigs[0]);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', waitForAsync(() => {
+ it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -104,17 +105,17 @@ describe('UserCallbackHandlerService', () => {
autoUserInfo: false,
},
];
- const spy = spyOn(flowsDataService, 'setSessionState');
+ const spy = vi.spyOn(flowsDataService, 'setSessionState');
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', waitForAsync(() => {
+ it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -138,17 +139,17 @@ describe('UserCallbackHandlerService', () => {
autoUserInfo: false,
},
];
- const spy = spyOn(flowsDataService, 'setSessionState');
+ const spy = vi.spyOn(flowsDataService, 'setSessionState');
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', waitForAsync(() => {
+ it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', async () => {
const svr = new StateValidationResult('accesstoken', '', true, '');
const callbackContext = {
code: '',
@@ -168,17 +169,17 @@ describe('UserCallbackHandlerService', () => {
},
];
- const spy = spyOn(flowsDataService, 'setSessionState');
+ const spy = vi.spyOn(flowsDataService, 'setSessionState');
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', waitForAsync(() => {
+ it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -204,24 +205,24 @@ describe('UserCallbackHandlerService', () => {
},
];
- const updateAndPublishAuthStateSpy = spyOn(
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: true,
validationResult: ValidationResult.NotSet,
isRenewProcess: false,
});
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', waitForAsync(() => {
+ it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -247,16 +248,17 @@ describe('UserCallbackHandlerService', () => {
},
];
- const getAndPersistUserDataInStoreSpy = spyOn(
- userService,
- 'getAndPersistUserDataInStore'
- ).and.returnValue(of({ user: 'some_data' }));
+ const getAndPersistUserDataInStoreSpy = vi
+ .spyOn(userService, 'getAndPersistUserDataInStore')
+ .mockReturnValue(of({ user: 'some_data' }));
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
- expect(getAndPersistUserDataInStoreSpy).toHaveBeenCalledOnceWith(
- allConfigs[0],
+ expect(
+ getAndPersistUserDataInStoreSpy
+ ).toHaveBeenCalledExactlyOnceWith(
+ allConfigs[0]!,
allConfigs,
false,
'idtoken',
@@ -264,9 +266,9 @@ describe('UserCallbackHandlerService', () => {
);
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', waitForAsync(() => {
+ it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -293,27 +295,27 @@ describe('UserCallbackHandlerService', () => {
},
];
- spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
+ vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
of({ user: 'some_data' })
);
- const updateAndPublishAuthStateSpy = spyOn(
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: true,
validationResult: ValidationResult.MaxOffsetExpired,
isRenewProcess: false,
});
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', waitForAsync(() => {
+ it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -340,23 +342,23 @@ describe('UserCallbackHandlerService', () => {
},
];
- spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
+ vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
of({ user: 'some_data' })
);
- const setSessionStateSpy = spyOn(flowsDataService, 'setSessionState');
+ const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState');
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe((resultCallbackContext) => {
- expect(setSessionStateSpy).toHaveBeenCalledOnceWith(
+ expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
'mystate',
allConfigs[0]
);
expect(resultCallbackContext).toEqual(callbackContext);
});
- }));
+ });
- it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', waitForAsync(() => {
+ it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -383,19 +385,21 @@ describe('UserCallbackHandlerService', () => {
},
];
- spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
+ vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
of(null)
);
- const updateAndPublishAuthStateSpy = spyOn(
+ const updateAndPublishAuthStateSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe({
error: (err) => {
- expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
+ expect(
+ updateAndPublishAuthStateSpy
+ ).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
validationResult: ValidationResult.MaxOffsetExpired,
isRenewProcess: false,
@@ -405,9 +409,9 @@ describe('UserCallbackHandlerService', () => {
);
},
});
- }));
+ });
- it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', waitForAsync(() => {
+ it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', async () => {
const svr = new StateValidationResult(
'accesstoken',
'idtoken',
@@ -434,16 +438,16 @@ describe('UserCallbackHandlerService', () => {
},
];
- spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
+ vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
of(null)
);
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
service
- .callbackUser(callbackContext, allConfigs[0], allConfigs)
+ .callbackUser(callbackContext, allConfigs[0]!, allConfigs)
.subscribe({
error: (err) => {
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
@@ -452,6 +456,6 @@ describe('UserCallbackHandlerService', () => {
);
},
});
- }));
+ });
});
});
diff --git a/src/flows/callback-handling/user-callback-handler.service.ts b/src/flows/callback-handling/user-callback-handler.service.ts
index ea0fa10..09730d1 100644
--- a/src/flows/callback-handling/user-callback-handler.service.ts
+++ b/src/flows/callback-handling/user-callback-handler.service.ts
@@ -1,12 +1,12 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { AuthStateService } from '../../auth-state/auth-state.service';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { LoggerService } from '../../logging/logger.service';
import { UserService } from '../../user-data/user.service';
-import { StateValidationResult } from '../../validation/state-validation-result';
-import { CallbackContext } from '../callback-context';
+import type { StateValidationResult } from '../../validation/state-validation-result';
+import type { CallbackContext } from '../callback-context';
import { FlowsDataService } from '../flows-data.service';
import { ResetAuthDataService } from '../reset-auth-data.service';
diff --git a/src/flows/flows-data.service.spec.ts b/src/flows/flows-data.service.spec.ts
index dc8e258..e5aa45f 100644
--- a/src/flows/flows-data.service.spec.ts
+++ b/src/flows/flows-data.service.spec.ts
@@ -1,7 +1,8 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { CryptoService } from '../utils/crypto/crypto.service';
import { FlowsDataService } from './flows-data.service';
import { RandomService } from './random/random.service';
@@ -37,12 +38,12 @@ describe('Flows Data Service', () => {
describe('createNonce', () => {
it('createNonce returns nonce and stores it', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
const result = service.createNonce({ configId: 'configId1' });
expect(result).toBeTruthy();
- expect(spy).toHaveBeenCalledOnceWith('authNonce', result, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authNonce', result, {
configId: 'configId1',
});
});
@@ -50,32 +51,38 @@ describe('Flows Data Service', () => {
describe('AuthStateControl', () => {
it('getAuthStateControl returns property from store', () => {
- const spy = spyOn(storagePersistenceService, 'read');
+ const spy = vi.spyOn(storagePersistenceService, 'read');
service.getAuthStateControl({ configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('authStateControl', {
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authStateControl', {
configId: 'configId1',
});
});
it('setAuthStateControl saves property in store', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.setAuthStateControl('ToSave', { configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('authStateControl', 'ToSave', {
- configId: 'configId1',
- });
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'authStateControl',
+ 'ToSave',
+ {
+ configId: 'configId1',
+ }
+ );
});
});
describe('getExistingOrCreateAuthStateControl', () => {
it('if nothing stored it creates a 40 char one and saves the authStateControl', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authStateControl', { configId: 'configId1' })
- .and.returnValue(null);
- const setSpy = spyOn(storagePersistenceService, 'write');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authStateControl', { configId: 'configId1' }],
+ () => null
+ );
+ const setSpy = vi.spyOn(storagePersistenceService, 'write');
const result = service.getExistingOrCreateAuthStateControl({
configId: 'configId1',
@@ -83,16 +90,22 @@ describe('Flows Data Service', () => {
expect(result).toBeTruthy();
expect(result.length).toBe(41);
- expect(setSpy).toHaveBeenCalledOnceWith('authStateControl', result, {
- configId: 'configId1',
- });
+ expect(setSpy).toHaveBeenCalledExactlyOnceWith(
+ 'authStateControl',
+ result,
+ {
+ configId: 'configId1',
+ }
+ );
});
it('if stored it returns the value and does NOT Store the value again', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authStateControl', { configId: 'configId1' })
- .and.returnValue('someAuthStateControl');
- const setSpy = spyOn(storagePersistenceService, 'write');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authStateControl', { configId: 'configId1' }],
+ () => 'someAuthStateControl'
+ );
+ const setSpy = vi.spyOn(storagePersistenceService, 'write');
const result = service.getExistingOrCreateAuthStateControl({
configId: 'configId1',
@@ -106,11 +119,11 @@ describe('Flows Data Service', () => {
describe('setSessionState', () => {
it('setSessionState saves the value in the storage', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.setSessionState('Genesis', { configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('session_state', 'Genesis', {
+ expect(spy).toHaveBeenCalledExactlyOnceWith('session_state', 'Genesis', {
configId: 'configId1',
});
});
@@ -118,7 +131,7 @@ describe('Flows Data Service', () => {
describe('resetStorageFlowData', () => {
it('resetStorageFlowData calls correct method on storagePersistenceService', () => {
- const spy = spyOn(storagePersistenceService, 'resetStorageFlowData');
+ const spy = vi.spyOn(storagePersistenceService, 'resetStorageFlowData');
service.resetStorageFlowData({ configId: 'configId1' });
@@ -128,26 +141,27 @@ describe('Flows Data Service', () => {
describe('codeVerifier', () => {
it('getCodeVerifier returns value from the store', () => {
- const spy = spyOn(storagePersistenceService, 'read')
+ const spy = vi
+ .spyOn(storagePersistenceService, 'read')
.withArgs('codeVerifier', { configId: 'configId1' })
- .and.returnValue('Genesis');
+ .mockReturnValue('Genesis');
const result = service.getCodeVerifier({ configId: 'configId1' });
expect(result).toBe('Genesis');
- expect(spy).toHaveBeenCalledOnceWith('codeVerifier', {
+ expect(spy).toHaveBeenCalledExactlyOnceWith('codeVerifier', {
configId: 'configId1',
});
});
it('createCodeVerifier returns random createCodeVerifier and stores it', () => {
- const setSpy = spyOn(storagePersistenceService, 'write');
+ const setSpy = vi.spyOn(storagePersistenceService, 'write');
const result = service.createCodeVerifier({ configId: 'configId1' });
expect(result).toBeTruthy();
expect(result.length).toBe(67);
- expect(setSpy).toHaveBeenCalledOnceWith('codeVerifier', result, {
+ expect(setSpy).toHaveBeenCalledExactlyOnceWith('codeVerifier', result, {
configId: 'configId1',
});
});
@@ -165,22 +179,26 @@ describe('Flows Data Service', () => {
jasmine.clock().mockDate(baseTime);
- spyOn(storagePersistenceService, 'read')
- .withArgs('storageCodeFlowInProgress', config)
- .and.returnValue(true);
- const spyWrite = spyOn(storagePersistenceService, 'write');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['storageCodeFlowInProgress', config],
+ () => true
+ );
+ const spyWrite = vi.spyOn(storagePersistenceService, 'write');
const isCodeFlowInProgressResult = service.isCodeFlowInProgress(config);
expect(spyWrite).not.toHaveBeenCalled();
- expect(isCodeFlowInProgressResult).toBeTrue();
+ expect(isCodeFlowInProgressResult).toBeTruthy();
});
it('state object does not exist returns false result', () => {
// arrange
- spyOn(storagePersistenceService, 'read')
- .withArgs('storageCodeFlowInProgress', { configId: 'configId1' })
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['storageCodeFlowInProgress', { configId: 'configId1' }],
+ () => null
+ );
// act
const isCodeFlowInProgressResult = service.isCodeFlowInProgress({
@@ -188,7 +206,7 @@ describe('Flows Data Service', () => {
});
// assert
- expect(isCodeFlowInProgressResult).toBeFalse();
+ expect(isCodeFlowInProgressResult).toBeFalsy();
});
});
@@ -200,23 +218,31 @@ describe('Flows Data Service', () => {
jasmine.clock().mockDate(baseTime);
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.setCodeFlowInProgress({ configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('storageCodeFlowInProgress', true, {
- configId: 'configId1',
- });
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'storageCodeFlowInProgress',
+ true,
+ {
+ configId: 'configId1',
+ }
+ );
});
});
describe('resetCodeFlowInProgress', () => {
it('set resetCodeFlowInProgress to false when called', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.resetCodeFlowInProgress({ configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('storageCodeFlowInProgress', false, {
- configId: 'configId1',
- });
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'storageCodeFlowInProgress',
+ false,
+ {
+ configId: 'configId1',
+ }
+ );
});
});
@@ -238,21 +264,21 @@ describe('Flows Data Service', () => {
dateOfLaunchedProcessUtc: baseTime.toISOString(),
};
- spyOn(storagePersistenceService, 'read')
+ vi.spyOn(storagePersistenceService, 'read')
.withArgs('storageSilentRenewRunning', config)
- .and.returnValue(JSON.stringify(storageObject));
- const spyWrite = spyOn(storagePersistenceService, 'write');
+ .mockReturnValue(JSON.stringify(storageObject));
+ const spyWrite = vi.spyOn(storagePersistenceService, 'write');
jasmine.clock().tick((config.silentRenewTimeoutInSeconds + 1) * 1000);
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
- expect(spyWrite).toHaveBeenCalledOnceWith(
+ expect(spyWrite).toHaveBeenCalledExactlyOnceWith(
'storageSilentRenewRunning',
'',
config
);
- expect(isSilentRenewRunningResult).toBeFalse();
+ expect(isSilentRenewRunningResult).toBeFalsy();
});
it('checks silent renew process and returns result', () => {
@@ -272,27 +298,29 @@ describe('Flows Data Service', () => {
dateOfLaunchedProcessUtc: baseTime.toISOString(),
};
- spyOn(storagePersistenceService, 'read')
+ vi.spyOn(storagePersistenceService, 'read')
.withArgs('storageSilentRenewRunning', config)
- .and.returnValue(JSON.stringify(storageObject));
- const spyWrite = spyOn(storagePersistenceService, 'write');
+ .mockReturnValue(JSON.stringify(storageObject));
+ const spyWrite = vi.spyOn(storagePersistenceService, 'write');
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
expect(spyWrite).not.toHaveBeenCalled();
- expect(isSilentRenewRunningResult).toBeTrue();
+ expect(isSilentRenewRunningResult).toBeTruthy();
});
it('state object does not exist returns false result', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('storageSilentRenewRunning', { configId: 'configId1' })
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['storageSilentRenewRunning', { configId: 'configId1' }],
+ () => null
+ );
const isSilentRenewRunningResult = service.isSilentRenewRunning({
configId: 'configId1',
});
- expect(isSilentRenewRunningResult).toBeFalse();
+ expect(isSilentRenewRunningResult).toBeFalsy();
});
});
@@ -309,10 +337,10 @@ describe('Flows Data Service', () => {
dateOfLaunchedProcessUtc: baseTime.toISOString(),
};
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.setSilentRenewRunning({ configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'storageSilentRenewRunning',
JSON.stringify(storageObject),
{ configId: 'configId1' }
@@ -322,12 +350,16 @@ describe('Flows Data Service', () => {
describe('resetSilentRenewRunning', () => {
it('set resetSilentRenewRunning to empty string when called', () => {
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
service.resetSilentRenewRunning({ configId: 'configId1' });
- expect(spy).toHaveBeenCalledOnceWith('storageSilentRenewRunning', '', {
- configId: 'configId1',
- });
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'storageSilentRenewRunning',
+ '',
+ {
+ configId: 'configId1',
+ }
+ );
});
});
});
diff --git a/src/flows/flows-data.service.ts b/src/flows/flows-data.service.ts
index 488ef37..42d55be 100644
--- a/src/flows/flows-data.service.ts
+++ b/src/flows/flows-data.service.ts
@@ -1,8 +1,8 @@
-import { inject, Injectable } from 'injection-js';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import { Injectable, inject } from 'injection-js';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { LoggerService } from '../logging/logger.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
-import { SilentRenewRunning } from './flows.models';
+import type { SilentRenewRunning } from './flows.models';
import { RandomService } from './random/random.service';
@Injectable()
@@ -18,7 +18,7 @@ export class FlowsDataService {
createNonce(configuration: OpenIdConfiguration): string {
const nonce = this.randomService.createRandom(40, configuration);
- this.loggerService.logDebug(configuration, 'Nonce created. nonce:' + nonce);
+ this.loggerService.logDebug(configuration, `Nonce created. nonce:${nonce}`);
this.setNonce(nonce, configuration);
return nonce;
diff --git a/src/flows/flows.service.spec.ts b/src/flows/flows.service.spec.ts
index 34c33ce..cd36d28 100644
--- a/src/flows/flows.service.spec.ts
+++ b/src/flows/flows.service.spec.ts
@@ -1,7 +1,8 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { CallbackContext } from './callback-context';
+import { vi } from 'vitest';
+import { mockProvider } from '../testing/mock';
+import type { CallbackContext } from './callback-context';
import { CodeFlowCallbackHandlerService } from './callback-handling/code-flow-callback-handler.service';
import { HistoryJwtKeysCallbackHandlerService } from './callback-handling/history-jwt-keys-callback-handler.service';
import { ImplicitFlowCallbackHandlerService } from './callback-handling/implicit-flow-callback-handler.service';
@@ -64,27 +65,25 @@ describe('Flows Service', () => {
});
describe('processCodeFlowCallback', () => {
- it('calls all methods correctly', waitForAsync(() => {
- const codeFlowCallbackSpy = spyOn(
- codeFlowCallbackHandlerService,
- 'codeFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
- const codeFlowCodeRequestSpy = spyOn(
- codeFlowCallbackHandlerService,
- 'codeFlowCodeRequest'
- ).and.returnValue(of({} as CallbackContext));
- const callbackHistoryAndResetJwtKeysSpy = spyOn(
- historyJwtKeysCallbackHandlerService,
- 'callbackHistoryAndResetJwtKeys'
- ).and.returnValue(of({} as CallbackContext));
- const callbackStateValidationSpy = spyOn(
- stateValidationCallbackHandlerService,
- 'callbackStateValidation'
- ).and.returnValue(of({} as CallbackContext));
- const callbackUserSpy = spyOn(
- userCallbackHandlerService,
- 'callbackUser'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls all methods correctly', async () => {
+ const codeFlowCallbackSpy = vi
+ .spyOn(codeFlowCallbackHandlerService, 'codeFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
+ const codeFlowCodeRequestSpy = vi
+ .spyOn(codeFlowCallbackHandlerService, 'codeFlowCodeRequest')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackHistoryAndResetJwtKeysSpy = vi
+ .spyOn(
+ historyJwtKeysCallbackHandlerService,
+ 'callbackHistoryAndResetJwtKeys'
+ )
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackStateValidationSpy = vi
+ .spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackUserSpy = vi
+ .spyOn(userCallbackHandlerService, 'callbackUser')
+ .mockReturnValue(of({} as CallbackContext));
const allConfigs = [
{
configId: 'configId1',
@@ -92,10 +91,10 @@ describe('Flows Service', () => {
];
service
- .processCodeFlowCallback('some-url1234', allConfigs[0], allConfigs)
+ .processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs)
.subscribe((value) => {
expect(value).toEqual({} as CallbackContext);
- expect(codeFlowCallbackSpy).toHaveBeenCalledOnceWith(
+ expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
'some-url1234',
allConfigs[0]
);
@@ -104,27 +103,26 @@ describe('Flows Service', () => {
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
});
- }));
+ });
});
describe('processSilentRenewCodeFlowCallback', () => {
- it('calls all methods correctly', waitForAsync(() => {
- const codeFlowCodeRequestSpy = spyOn(
- codeFlowCallbackHandlerService,
- 'codeFlowCodeRequest'
- ).and.returnValue(of({} as CallbackContext));
- const callbackHistoryAndResetJwtKeysSpy = spyOn(
- historyJwtKeysCallbackHandlerService,
- 'callbackHistoryAndResetJwtKeys'
- ).and.returnValue(of({} as CallbackContext));
- const callbackStateValidationSpy = spyOn(
- stateValidationCallbackHandlerService,
- 'callbackStateValidation'
- ).and.returnValue(of({} as CallbackContext));
- const callbackUserSpy = spyOn(
- userCallbackHandlerService,
- 'callbackUser'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls all methods correctly', async () => {
+ const codeFlowCodeRequestSpy = vi
+ .spyOn(codeFlowCallbackHandlerService, 'codeFlowCodeRequest')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackHistoryAndResetJwtKeysSpy = vi
+ .spyOn(
+ historyJwtKeysCallbackHandlerService,
+ 'callbackHistoryAndResetJwtKeys'
+ )
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackStateValidationSpy = vi
+ .spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackUserSpy = vi
+ .spyOn(userCallbackHandlerService, 'callbackUser')
+ .mockReturnValue(of({} as CallbackContext));
const allConfigs = [
{
configId: 'configId1',
@@ -134,7 +132,7 @@ describe('Flows Service', () => {
service
.processSilentRenewCodeFlowCallback(
{} as CallbackContext,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
)
.subscribe((value) => {
@@ -144,27 +142,26 @@ describe('Flows Service', () => {
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled();
});
- }));
+ });
});
describe('processImplicitFlowCallback', () => {
- it('calls all methods correctly', waitForAsync(() => {
- const implicitFlowCallbackSpy = spyOn(
- implicitFlowCallbackHandlerService,
- 'implicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
- const callbackHistoryAndResetJwtKeysSpy = spyOn(
- historyJwtKeysCallbackHandlerService,
- 'callbackHistoryAndResetJwtKeys'
- ).and.returnValue(of({} as CallbackContext));
- const callbackStateValidationSpy = spyOn(
- stateValidationCallbackHandlerService,
- 'callbackStateValidation'
- ).and.returnValue(of({} as CallbackContext));
- const callbackUserSpy = spyOn(
- userCallbackHandlerService,
- 'callbackUser'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls all methods correctly', async () => {
+ const implicitFlowCallbackSpy = vi
+ .spyOn(implicitFlowCallbackHandlerService, 'implicitFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackHistoryAndResetJwtKeysSpy = vi
+ .spyOn(
+ historyJwtKeysCallbackHandlerService,
+ 'callbackHistoryAndResetJwtKeys'
+ )
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackStateValidationSpy = vi
+ .spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackUserSpy = vi
+ .spyOn(userCallbackHandlerService, 'callbackUser')
+ .mockReturnValue(of({} as CallbackContext));
const allConfigs = [
{
configId: 'configId1',
@@ -172,7 +169,7 @@ describe('Flows Service', () => {
];
service
- .processImplicitFlowCallback(allConfigs[0], allConfigs, 'any-hash')
+ .processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
.subscribe((value) => {
expect(value).toEqual({} as CallbackContext);
expect(implicitFlowCallbackSpy).toHaveBeenCalled();
@@ -180,31 +177,32 @@ describe('Flows Service', () => {
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled();
});
- }));
+ });
});
describe('processRefreshToken', () => {
- it('calls all methods correctly', waitForAsync(() => {
- const refreshSessionWithRefreshTokensSpy = spyOn(
- refreshSessionCallbackHandlerService,
- 'refreshSessionWithRefreshTokens'
- ).and.returnValue(of({} as CallbackContext));
- const refreshTokensRequestTokensSpy = spyOn(
- refreshTokenCallbackHandlerService,
- 'refreshTokensRequestTokens'
- ).and.returnValue(of({} as CallbackContext));
- const callbackHistoryAndResetJwtKeysSpy = spyOn(
- historyJwtKeysCallbackHandlerService,
- 'callbackHistoryAndResetJwtKeys'
- ).and.returnValue(of({} as CallbackContext));
- const callbackStateValidationSpy = spyOn(
- stateValidationCallbackHandlerService,
- 'callbackStateValidation'
- ).and.returnValue(of({} as CallbackContext));
- const callbackUserSpy = spyOn(
- userCallbackHandlerService,
- 'callbackUser'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls all methods correctly', async () => {
+ const refreshSessionWithRefreshTokensSpy = vi
+ .spyOn(
+ refreshSessionCallbackHandlerService,
+ 'refreshSessionWithRefreshTokens'
+ )
+ .mockReturnValue(of({} as CallbackContext));
+ const refreshTokensRequestTokensSpy = vi
+ .spyOn(refreshTokenCallbackHandlerService, 'refreshTokensRequestTokens')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackHistoryAndResetJwtKeysSpy = vi
+ .spyOn(
+ historyJwtKeysCallbackHandlerService,
+ 'callbackHistoryAndResetJwtKeys'
+ )
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackStateValidationSpy = vi
+ .spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
+ .mockReturnValue(of({} as CallbackContext));
+ const callbackUserSpy = vi
+ .spyOn(userCallbackHandlerService, 'callbackUser')
+ .mockReturnValue(of({} as CallbackContext));
const allConfigs = [
{
configId: 'configId1',
@@ -212,7 +210,7 @@ describe('Flows Service', () => {
];
service
- .processRefreshToken(allConfigs[0], allConfigs)
+ .processRefreshToken(allConfigs[0]!, allConfigs)
.subscribe((value) => {
expect(value).toEqual({} as CallbackContext);
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
@@ -221,6 +219,6 @@ describe('Flows Service', () => {
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled();
});
- }));
+ });
});
});
diff --git a/src/flows/flows.service.ts b/src/flows/flows.service.ts
index c06024d..9026b6e 100644
--- a/src/flows/flows.service.ts
+++ b/src/flows/flows.service.ts
@@ -1,8 +1,8 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import type { Observable } from 'rxjs';
import { concatMap } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from './callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from './callback-context';
import { CodeFlowCallbackHandlerService } from './callback-handling/code-flow-callback-handler.service';
import { HistoryJwtKeysCallbackHandlerService } from './callback-handling/history-jwt-keys-callback-handler.service';
import { ImplicitFlowCallbackHandlerService } from './callback-handling/implicit-flow-callback-handler.service';
diff --git a/src/flows/random/random.service.spec.ts b/src/flows/random/random.service.spec.ts
index 44f6aa6..1660b4e 100644
--- a/src/flows/random/random.service.spec.ts
+++ b/src/flows/random/random.service.spec.ts
@@ -1,6 +1,7 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { CryptoService } from '../../utils/crypto/crypto.service';
import { RandomService } from './random.service';
diff --git a/src/flows/reset-auth-data.service.spec.ts b/src/flows/reset-auth-data.service.spec.ts
index b19b2cf..7de2d26 100644
--- a/src/flows/reset-auth-data.service.spec.ts
+++ b/src/flows/reset-auth-data.service.spec.ts
@@ -1,7 +1,8 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { UserService } from '../user-data/user.service';
import { FlowsDataService } from './flows-data.service';
import { ResetAuthDataService } from './reset-auth-data.service';
@@ -37,7 +38,7 @@ describe('ResetAuthDataService', () => {
describe('resetAuthorizationData', () => {
it('calls resetUserDataInStore when autoUserInfo is true', () => {
- const resetUserDataInStoreSpy = spyOn(
+ const resetUserDataInStoreSpy = vi.spyOn(
userService,
'resetUserDataInStore'
);
@@ -47,16 +48,16 @@ describe('ResetAuthDataService', () => {
},
];
- service.resetAuthorizationData(allConfigs[0], allConfigs);
+ service.resetAuthorizationData(allConfigs[0]!, allConfigs);
expect(resetUserDataInStoreSpy).toHaveBeenCalled();
});
it('calls correct methods', () => {
- const resetStorageFlowDataSpy = spyOn(
+ const resetStorageFlowDataSpy = vi.spyOn(
flowsDataService,
'resetStorageFlowData'
);
- const setUnauthorizedAndFireEventSpy = spyOn(
+ const setUnauthorizedAndFireEventSpy = vi.spyOn(
authStateService,
'setUnauthenticatedAndFireEvent'
);
@@ -66,7 +67,7 @@ describe('ResetAuthDataService', () => {
},
];
- service.resetAuthorizationData(allConfigs[0], allConfigs);
+ service.resetAuthorizationData(allConfigs[0]!, allConfigs);
expect(resetStorageFlowDataSpy).toHaveBeenCalled();
expect(setUnauthorizedAndFireEventSpy).toHaveBeenCalled();
diff --git a/src/flows/reset-auth-data.service.ts b/src/flows/reset-auth-data.service.ts
index 1b327c5..1caa4e1 100644
--- a/src/flows/reset-auth-data.service.ts
+++ b/src/flows/reset-auth-data.service.ts
@@ -1,6 +1,6 @@
-import { inject, Injectable } from 'injection-js';
+import { Injectable, inject } from 'injection-js';
import { AuthStateService } from '../auth-state/auth-state.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { LoggerService } from '../logging/logger.service';
import { UserService } from '../user-data/user.service';
import { FlowsDataService } from './flows-data.service';
diff --git a/src/flows/signin-key-data.service.spec.ts b/src/flows/signin-key-data.service.spec.ts
index 08fb0f4..9193722 100644
--- a/src/flows/signin-key-data.service.spec.ts
+++ b/src/flows/signin-key-data.service.spec.ts
@@ -1,11 +1,12 @@
-import { HttpResponse } from '@angular/common/http';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
+import { HttpResponse } from '@ngify/http';
import { isObservable, of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { createRetriableStream } from '../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../api/data.service';
import { LoggerService } from '../logging/logger.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { createRetriableStream } from '../testing/create-retriable-stream.helper';
+import { mockProvider } from '../testing/mock';
import { SigninKeyDataService } from './signin-key-data.service';
const DUMMY_JWKS = {
@@ -53,10 +54,12 @@ describe('Signin Key Data Service', () => {
});
describe('getSigningKeys', () => {
- it('throws error when no wellKnownEndpoints given', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue(null);
+ it('throws error when no wellKnownEndpoints given', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => null
+ );
const result = service.getSigningKeys({ configId: 'configId1' });
result.subscribe({
@@ -64,12 +67,14 @@ describe('Signin Key Data Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('throws error when no jwksUri given', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ jwksUri: null });
+ it('throws error when no jwksUri given', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ jwksUri: null })
+ );
const result = service.getSigningKeys({ configId: 'configId1' });
result.subscribe({
@@ -77,30 +82,34 @@ describe('Signin Key Data Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('calls dataservice if jwksurl is given', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ jwksUri: 'someUrl' });
- const spy = spyOn(dataService, 'get').and.callFake(() => of());
+ it('calls dataservice if jwksurl is given', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ jwksUri: 'someUrl' })
+ );
+ const spy = vi.spyOn(dataService, 'get').mockImplementation(() => of());
const result = service.getSigningKeys({ configId: 'configId1' });
result.subscribe({
complete: () => {
- expect(spy).toHaveBeenCalledOnceWith('someUrl', {
+ expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl', {
configId: 'configId1',
});
},
});
- }));
+ });
- it('should retry once', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ jwksUri: 'someUrl' });
- spyOn(dataService, 'get').and.returnValue(
+ it('should retry once', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ jwksUri: 'someUrl' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
of(DUMMY_JWKS)
@@ -113,13 +122,15 @@ describe('Signin Key Data Service', () => {
expect(res).toEqual(DUMMY_JWKS);
},
});
- }));
+ });
- it('should retry twice', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ jwksUri: 'someUrl' });
- spyOn(dataService, 'get').and.returnValue(
+ it('should retry twice', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ jwksUri: 'someUrl' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -133,13 +144,15 @@ describe('Signin Key Data Service', () => {
expect(res).toEqual(DUMMY_JWKS);
},
});
- }));
+ });
- it('should fail after three tries', waitForAsync(() => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ jwksUri: 'someUrl' });
- spyOn(dataService, 'get').and.returnValue(
+ it('should fail after three tries', async () => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ jwksUri: 'someUrl' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -153,21 +166,21 @@ describe('Signin Key Data Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
describe('handleErrorGetSigningKeys', () => {
- it('keeps observable if error is catched', waitForAsync(() => {
+ it('keeps observable if error is catched', async () => {
const result = (service as any).handleErrorGetSigningKeys(
new HttpResponse()
);
const hasTypeObservable = isObservable(result);
- expect(hasTypeObservable).toBeTrue();
- }));
+ expect(hasTypeObservable).toBeTruthy();
+ });
- it('logs error if error is response', waitForAsync(() => {
- const logSpy = spyOn(loggerService, 'logError');
+ it('logs error if error is response', async () => {
+ const logSpy = vi.spyOn(loggerService, 'logError');
(service as any)
.handleErrorGetSigningKeys(
@@ -176,31 +189,31 @@ describe('Signin Key Data Service', () => {
)
.subscribe({
error: () => {
- expect(logSpy).toHaveBeenCalledOnceWith(
+ expect(logSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'400 - nono {}'
);
},
});
- }));
+ });
- it('logs error if error is not a response', waitForAsync(() => {
- const logSpy = spyOn(loggerService, 'logError');
+ it('logs error if error is not a response', async () => {
+ const logSpy = vi.spyOn(loggerService, 'logError');
(service as any)
.handleErrorGetSigningKeys('Just some Error', { configId: 'configId1' })
.subscribe({
error: () => {
- expect(logSpy).toHaveBeenCalledOnceWith(
+ expect(logSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'Just some Error'
);
},
});
- }));
+ });
- it('logs error if error with message property is not a response', waitForAsync(() => {
- const logSpy = spyOn(loggerService, 'logError');
+ it('logs error if error with message property is not a response', async () => {
+ const logSpy = vi.spyOn(loggerService, 'logError');
(service as any)
.handleErrorGetSigningKeys(
@@ -209,12 +222,12 @@ describe('Signin Key Data Service', () => {
)
.subscribe({
error: () => {
- expect(logSpy).toHaveBeenCalledOnceWith(
+ expect(logSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'Just some Error'
);
},
});
- }));
+ });
});
});
diff --git a/src/http/index.ts b/src/http/index.ts
new file mode 100644
index 0000000..ad689bb
--- /dev/null
+++ b/src/http/index.ts
@@ -0,0 +1,11 @@
+import type { HttpFeature } from '@ngify/http';
+
+export function provideHttpClient() {
+ // todo
+ throw new Error('todo!');
+}
+
+export function withInterceptorsFromDi(): HttpFeature {
+ // todo
+ throw new Error('todo!');
+}
diff --git a/src/iframe/check-session.service.spec.ts b/src/iframe/check-session.service.spec.ts
index db4db75..7e957c4 100644
--- a/src/iframe/check-session.service.spec.ts
+++ b/src/iframe/check-session.service.spec.ts
@@ -1,13 +1,14 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
import { of } from 'rxjs';
import { skip } from 'rxjs/operators';
-import { mockAbstractProvider, mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
import { OidcSecurityService } from '../oidc.security.service';
import { PublicEventsService } from '../public-events/public-events.service';
import { AbstractSecurityStorage } from '../storage/abstract-security-storage';
import { DefaultSessionStorageService } from '../storage/default-sessionstorage.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockAbstractProvider, mockProvider } from '../testing/mock';
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
import { CheckSessionService } from './check-session.service';
import { IFrameService } from './existing-iframe.service';
@@ -67,7 +68,7 @@ describe('CheckSessionService', () => {
});
it('getOrCreateIframe calls iFrameService.addIFrameToWindowBody if no Iframe exists', () => {
- spyOn(iFrameService, 'addIFrameToWindowBody').and.callThrough();
+ vi.spyOn(iFrameService, 'addIFrameToWindowBody')();
const result = (checkSessionService as any).getOrCreateIframe({
configId: 'configId1',
@@ -89,7 +90,7 @@ describe('CheckSessionService', () => {
it('init appends iframe on body with correct values', () => {
expect((checkSessionService as any).sessionIframe).toBeFalsy();
- spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
+ vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
(checkSessionService as any).init();
const iframe = (checkSessionService as any).getOrCreateIframe({
@@ -105,29 +106,34 @@ describe('CheckSessionService', () => {
});
it('log warning if authWellKnownEndpoints.check_session_iframe is not existing', () => {
- const spyLogWarning = spyOn(loggerService, 'logWarning');
+ const spyLogWarning = vi.spyOn(loggerService, 'logWarning');
const config = { configId: 'configId1' };
- spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
- spyOn(storagePersistenceService, 'read')
+ vi.spyOn(loggerService, 'logDebug').mockImplementation(
+ () => undefined
+ );
+ vi.spyOn(storagePersistenceService, 'read')
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ checkSessionIframe: undefined });
+ .mockReturnValue({ checkSessionIframe: undefined });
(checkSessionService as any).init(config);
- expect(spyLogWarning).toHaveBeenCalledOnceWith(config, jasmine.any(String));
+ expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
+ config,
+ expect.any(String)
+ );
});
it('start() calls pollserversession() with clientId if no scheduledheartbeat is set', () => {
- const spy = spyOn(checkSessionService, 'pollServerSession');
+ const spy = vi.spyOn(checkSessionService, 'pollServerSession');
const config = { clientId: 'clientId', configId: 'configId1' };
checkSessionService.start(config);
- expect(spy).toHaveBeenCalledOnceWith('clientId', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('clientId', config);
});
it('start() does not call pollServerSession() if scheduledHeartBeatRunning is set', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(checkSessionService, 'pollServerSession');
+ const spy = vi.spyOn(checkSessionService, 'pollServerSession');
(checkSessionService as any).scheduledHeartBeatRunning = (): void =>
undefined;
@@ -148,10 +154,10 @@ describe('CheckSessionService', () => {
it('stopCheckingSession does nothing if scheduledHeartBeatRunning is not set', () => {
(checkSessionService as any).scheduledHeartBeatRunning = null;
- const spy = spyOn(checkSessionService, 'clearScheduledHeartBeat');
+ const spy = vi.spyOn(checkSessionService, 'clearScheduledHeartBeat');
checkSessionService.stop();
- expect(spy).not.toHaveBeenCalledOnceWith();
+ expect(spy).not.toHaveBeenCalledExactlyOnceWith();
});
describe('serverStateChanged', () => {
@@ -167,7 +173,7 @@ describe('CheckSessionService', () => {
const config = { startCheckSession: true, configId: 'configId1' };
const result = checkSessionService.serverStateChanged(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('returns true if startCheckSession is configured and checkSessionReceived is true', () => {
@@ -175,17 +181,17 @@ describe('CheckSessionService', () => {
const config = { startCheckSession: true, configId: 'configId1' };
const result = checkSessionService.serverStateChanged(config);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
});
describe('pollServerSession', () => {
beforeEach(() => {
- spyOn(checkSessionService, 'init').and.returnValue(of(undefined));
+ vi.spyOn(checkSessionService, 'init').mockReturnValue(of(undefined));
});
it('increases outstandingMessages', () => {
- spyOn(checkSessionService, 'getExistingIframe').and.returnValue({
+ vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue({
contentWindow: { postMessage: () => undefined },
});
const authWellKnownEndpoints = {
@@ -193,18 +199,20 @@ describe('CheckSessionService', () => {
};
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints)
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => authWellKnownEndpoints
+ )
.withArgs('session_state', config)
- .and.returnValue('session_state');
- spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
+ .mockReturnValue('session_state');
+ vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
(checkSessionService as any).pollServerSession('clientId', config);
expect((checkSessionService as any).outstandingMessages).toBe(1);
});
it('logs warning if iframe does not exist', () => {
- spyOn(checkSessionService, 'getExistingIframe').and.returnValue(
+ vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue(
null
);
const authWellKnownEndpoints = {
@@ -212,77 +220,91 @@ describe('CheckSessionService', () => {
};
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
- const spyLogWarning = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => authWellKnownEndpoints
);
+ const spyLogWarning = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
- spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
+ vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
(checkSessionService as any).pollServerSession('clientId', config);
- expect(spyLogWarning).toHaveBeenCalledOnceWith(
+ expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
config,
- jasmine.any(String)
+ expect.any(String)
);
});
it('logs warning if clientId is not set', () => {
- spyOn(checkSessionService, 'getExistingIframe').and.returnValue({});
+ vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue(
+ {}
+ );
const authWellKnownEndpoints = {
checkSessionIframe: 'https://some-testing-url.com',
};
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
- const spyLogWarning = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => authWellKnownEndpoints
);
+ const spyLogWarning = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
- spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
+ vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
(checkSessionService as any).pollServerSession('', config);
- expect(spyLogWarning).toHaveBeenCalledOnceWith(
+ expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
config,
- jasmine.any(String)
+ expect.any(String)
);
});
it('logs debug if session_state is not set', () => {
- spyOn(checkSessionService, 'getExistingIframe').and.returnValue({});
+ vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue(
+ {}
+ );
const authWellKnownEndpoints = {
checkSessionIframe: 'https://some-testing-url.com',
};
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints)
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => authWellKnownEndpoints
+ )
.withArgs('session_state', config)
- .and.returnValue(null);
+ .mockReturnValue(null);
- const spyLogDebug = spyOn(loggerService, 'logDebug').and.callFake(
- () => undefined
- );
+ const spyLogDebug = vi
+ .spyOn(loggerService, 'logDebug')
+ .mockImplementation(() => undefined);
(checkSessionService as any).pollServerSession('clientId', config);
expect(spyLogDebug).toHaveBeenCalledTimes(2);
});
it('logs debug if session_state is set but authWellKnownEndpoints are not set', () => {
- spyOn(checkSessionService, 'getExistingIframe').and.returnValue({});
+ vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue(
+ {}
+ );
const authWellKnownEndpoints = null;
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints)
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => authWellKnownEndpoints
+ )
.withArgs('session_state', config)
- .and.returnValue('some_session_state');
- const spyLogDebug = spyOn(loggerService, 'logDebug').and.callFake(
- () => undefined
- );
+ .mockReturnValue('some_session_state');
+ const spyLogDebug = vi
+ .spyOn(loggerService, 'logDebug')
+ .mockImplementation(() => undefined);
(checkSessionService as any).pollServerSession('clientId', config);
expect(spyLogDebug).toHaveBeenCalledTimes(2);
@@ -290,7 +312,7 @@ describe('CheckSessionService', () => {
});
describe('init', () => {
- it('returns falsy observable when lastIframerefresh and iframeRefreshInterval are bigger than now', waitForAsync(() => {
+ it('returns falsy observable when lastIframerefresh and iframeRefreshInterval are bigger than now', async () => {
const serviceAsAny = checkSessionService as any;
const dateNow = new Date();
const lastRefresh = dateNow.setMinutes(dateNow.getMinutes() + 30);
@@ -301,7 +323,7 @@ describe('CheckSessionService', () => {
serviceAsAny.init().subscribe((result: any) => {
expect(result).toBeUndefined();
});
- }));
+ });
});
describe('isCheckSessionConfigured', () => {
@@ -323,7 +345,7 @@ describe('CheckSessionService', () => {
});
describe('checkSessionChanged$', () => {
- it('emits when internal event is thrown', waitForAsync(() => {
+ it('emits when internal event is thrown', async () => {
checkSessionService.checkSessionChanged$
.pipe(skip(1))
.subscribe((result) => {
@@ -333,15 +355,15 @@ describe('CheckSessionService', () => {
const serviceAsAny = checkSessionService as any;
serviceAsAny.checkSessionChangedInternal$.next(true);
- }));
+ });
- it('emits false initially', waitForAsync(() => {
+ it('emits false initially', async () => {
checkSessionService.checkSessionChanged$.subscribe((result) => {
expect(result).toBe(false);
});
- }));
+ });
- it('emits false then true when emitted', waitForAsync(() => {
+ it('emits false then true when emitted', async () => {
const expectedResultsInOrder = [false, true];
let counter = 0;
@@ -351,6 +373,6 @@ describe('CheckSessionService', () => {
});
(checkSessionService as any).checkSessionChangedInternal$.next(true);
- }));
+ });
});
});
diff --git a/src/iframe/refresh-session-iframe.service.spec.ts b/src/iframe/refresh-session-iframe.service.spec.ts
index 1dd2fca..0bd4c4a 100644
--- a/src/iframe/refresh-session-iframe.service.spec.ts
+++ b/src/iframe/refresh-session-iframe.service.spec.ts
@@ -1,7 +1,8 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { UrlService } from '../utils/url/url.service';
import { RefreshSessionIframeService } from './refresh-session-iframe.service';
import { SilentRenewService } from './silent-renew.service';
@@ -31,37 +32,43 @@ describe('RefreshSessionIframeService ', () => {
});
describe('refreshSessionWithIframe', () => {
- it('calls sendAuthorizeRequestUsingSilentRenew with created url', waitForAsync(() => {
- spyOn(urlService, 'getRefreshSessionSilentRenewUrl').and.returnValue(
+ it('calls sendAuthorizeRequestUsingSilentRenew with created url', async () => {
+ vi.spyOn(urlService, 'getRefreshSessionSilentRenewUrl').mockReturnValue(
of('a-url')
);
- const sendAuthorizeRequestUsingSilentRenewSpy = spyOn(
- refreshSessionIframeService as any,
- 'sendAuthorizeRequestUsingSilentRenew'
- ).and.returnValue(of(null));
+ const sendAuthorizeRequestUsingSilentRenewSpy = vi
+ .spyOn(
+ refreshSessionIframeService as any,
+ 'sendAuthorizeRequestUsingSilentRenew'
+ )
+ .mockReturnValue(of(null));
const allConfigs = [{ configId: 'configId1' }];
refreshSessionIframeService
- .refreshSessionWithIframe(allConfigs[0], allConfigs)
+ .refreshSessionWithIframe(allConfigs[0]!, allConfigs)
.subscribe(() => {
expect(
sendAuthorizeRequestUsingSilentRenewSpy
- ).toHaveBeenCalledOnceWith('a-url', allConfigs[0], allConfigs);
+ ).toHaveBeenCalledExactlyOnceWith(
+ 'a-url',
+ allConfigs[0]!,
+ allConfigs
+ );
});
- }));
+ });
});
describe('initSilentRenewRequest', () => {
- it('dispatches customevent to window object', waitForAsync(() => {
- const dispatchEventSpy = spyOn(window, 'dispatchEvent');
+ it('dispatches customevent to window object', async () => {
+ const dispatchEventSpy = vi.spyOn(window, 'dispatchEvent');
(refreshSessionIframeService as any).initSilentRenewRequest();
- expect(dispatchEventSpy).toHaveBeenCalledOnceWith(
+ expect(dispatchEventSpy).toHaveBeenCalledExactlyOnceWith(
new CustomEvent('oidc-silent-renew-init', {
- detail: jasmine.any(Number),
+ detail: expect.any(Number),
})
);
- }));
+ });
});
});
diff --git a/src/iframe/refresh-session-iframe.service.ts b/src/iframe/refresh-session-iframe.service.ts
index db9ed49..345c61a 100644
--- a/src/iframe/refresh-session-iframe.service.ts
+++ b/src/iframe/refresh-session-iframe.service.ts
@@ -1,8 +1,8 @@
-import { DOCUMENT } from '../dom';
import { Injectable, RendererFactory2, inject } from 'injection-js';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import { DOCUMENT } from '../dom';
import { LoggerService } from '../logging/logger.service';
import { UrlService } from '../utils/url/url.service';
import { SilentRenewService } from './silent-renew.service';
diff --git a/src/iframe/silent-renew.service.spec.ts b/src/iframe/silent-renew.service.spec.ts
index da0d92f..53719fb 100644
--- a/src/iframe/silent-renew.service.spec.ts
+++ b/src/iframe/silent-renew.service.spec.ts
@@ -1,14 +1,15 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
+import { TestBed, fakeAsync, tick } from '@/testing';
import { Observable, of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ImplicitFlowCallbackService } from '../callback/implicit-flow-callback.service';
import { IntervalService } from '../callback/interval.service';
-import { CallbackContext } from '../flows/callback-context';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { ValidationResult } from '../validation/validation-result';
import { IFrameService } from './existing-iframe.service';
@@ -63,7 +64,7 @@ describe('SilentRenewService ', () => {
describe('refreshSessionWithIFrameCompleted', () => {
it('is of type observable', () => {
expect(silentRenewService.refreshSessionWithIFrameCompleted$).toEqual(
- jasmine.any(Observable)
+ expect.any(Observable)
);
});
});
@@ -95,7 +96,7 @@ describe('SilentRenewService ', () => {
describe('getOrCreateIframe', () => {
it('returns iframe if iframe is truthy', () => {
- spyOn(silentRenewService as any, 'getExistingIframe').and.returnValue({
+ vi.spyOn(silentRenewService as any, 'getExistingIframe').mockReturnValue({
name: 'anything',
});
@@ -109,31 +110,33 @@ describe('SilentRenewService ', () => {
it('adds iframe to body if existing iframe is falsy', () => {
const config = { configId: 'configId1' };
- spyOn(silentRenewService as any, 'getExistingIframe').and.returnValue(
+ vi.spyOn(silentRenewService as any, 'getExistingIframe').mockReturnValue(
null
);
- const spy = spyOn(iFrameService, 'addIFrameToWindowBody').and.returnValue(
- { name: 'anything' } as HTMLIFrameElement
- );
+ const spy = vi
+ .spyOn(iFrameService, 'addIFrameToWindowBody')
+ .mockReturnValue({ name: 'anything' } as HTMLIFrameElement);
const result = silentRenewService.getOrCreateIframe(config);
expect(result).toEqual({ name: 'anything' } as HTMLIFrameElement);
expect(spy).toHaveBeenCalledTimes(1);
- expect(spy).toHaveBeenCalledOnceWith('myiFrameForSilentRenew', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'myiFrameForSilentRenew',
+ config
+ );
});
});
describe('codeFlowCallbackSilentRenewIframe', () => {
- it('calls processSilentRenewCodeFlowCallback with correct arguments', waitForAsync(() => {
+ it('calls processSilentRenewCodeFlowCallback with correct arguments', async () => {
const config = { configId: 'configId1' };
const allConfigs = [config];
- const spy = spyOn(
- flowsService,
- 'processSilentRenewCodeFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ const spy = vi
+ .spyOn(flowsService, 'processSilentRenewCodeFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
const expectedContext = {
code: 'some-code',
refreshToken: '',
@@ -152,32 +155,31 @@ describe('SilentRenewService ', () => {
silentRenewService
.codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs)
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
expectedContext,
config,
allConfigs
);
});
- }));
+ });
- it('throws error if url has error param and resets everything on error', waitForAsync(() => {
+ it('throws error if url has error param and resets everything on error', async () => {
const config = { configId: 'configId1' };
const allConfigs = [config];
- const spy = spyOn(
- flowsService,
- 'processSilentRenewCodeFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
- const authStateServiceSpy = spyOn(
+ const spy = vi
+ .spyOn(flowsService, 'processSilentRenewCodeFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
+ const authStateServiceSpy = vi.spyOn(
authStateService,
'updateAndPublishAuthState'
);
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const setNonceSpy = spyOn(flowsDataService, 'setNonce');
- const stopPeriodicTokenCheckSpy = spyOn(
+ const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
+ const stopPeriodicTokenCheckSpy = vi.spyOn(
intervalService,
'stopPeriodicTokenCheck'
);
@@ -191,121 +193,116 @@ describe('SilentRenewService ', () => {
error: (error) => {
expect(error).toEqual(new Error('some_error'));
expect(spy).not.toHaveBeenCalled();
- expect(authStateServiceSpy).toHaveBeenCalledOnceWith({
+ expect(authStateServiceSpy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: false,
validationResult: ValidationResult.LoginRequired,
isRenewProcess: true,
});
- expect(resetAuthorizationDataSpy).toHaveBeenCalledOnceWith(
+ expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
config,
allConfigs
);
- expect(setNonceSpy).toHaveBeenCalledOnceWith('', config);
+ expect(setNonceSpy).toHaveBeenCalledExactlyOnceWith('', config);
expect(stopPeriodicTokenCheckSpy).toHaveBeenCalledTimes(1);
},
});
- }));
+ });
});
describe('silentRenewEventHandler', () => {
- it('returns if no details is given', fakeAsync(() => {
- const isCurrentFlowCodeFlowSpy = spyOn(
- flowHelper,
- 'isCurrentFlowCodeFlow'
- ).and.returnValue(false);
+ it('returns if no details is given', async () => {
+ const isCurrentFlowCodeFlowSpy = vi
+ .spyOn(flowHelper, 'isCurrentFlowCodeFlow')
+ .mockReturnValue(false);
- spyOn(
+ vi.spyOn(
implicitFlowCallbackService,
'authenticatedImplicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ ).mockReturnValue(of({} as CallbackContext));
const eventData = { detail: null } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }];
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
expect(isCurrentFlowCodeFlowSpy).not.toHaveBeenCalled();
- }));
+ });
- it('calls authorizedImplicitFlowCallback if current flow is not code flow', fakeAsync(() => {
- const isCurrentFlowCodeFlowSpy = spyOn(
- flowHelper,
- 'isCurrentFlowCodeFlow'
- ).and.returnValue(false);
- const authorizedImplicitFlowCallbackSpy = spyOn(
- implicitFlowCallbackService,
- 'authenticatedImplicitFlowCallback'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls authorizedImplicitFlowCallback if current flow is not code flow', async () => {
+ const isCurrentFlowCodeFlowSpy = vi
+ .spyOn(flowHelper, 'isCurrentFlowCodeFlow')
+ .mockReturnValue(false);
+ const authorizedImplicitFlowCallbackSpy = vi
+ .spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
+ .mockReturnValue(of({} as CallbackContext));
const eventData = { detail: 'detail' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }];
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
expect(isCurrentFlowCodeFlowSpy).toHaveBeenCalled();
- expect(authorizedImplicitFlowCallbackSpy).toHaveBeenCalledOnceWith(
- allConfigs[0],
+ expect(authorizedImplicitFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
+ allConfigs[0]!,
allConfigs,
'detail'
);
- }));
+ });
- it('calls codeFlowCallbackSilentRenewIframe if current flow is code flow', fakeAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- const codeFlowCallbackSilentRenewIframe = spyOn(
- silentRenewService,
- 'codeFlowCallbackSilentRenewIframe'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls codeFlowCallbackSilentRenewIframe if current flow is code flow', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ const codeFlowCallbackSilentRenewIframe = vi
+ .spyOn(silentRenewService, 'codeFlowCallbackSilentRenewIframe')
+ .mockReturnValue(of({} as CallbackContext));
const eventData = { detail: 'detail?detail2' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }];
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
- expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledOnceWith(
+ await vi.advanceTimersByTimeAsync(1000);
+ expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledExactlyOnceWith(
['detail', 'detail2'],
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- }));
+ });
- it('calls authorizedImplicitFlowCallback if current flow is not code flow', fakeAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- const codeFlowCallbackSilentRenewIframe = spyOn(
- silentRenewService,
- 'codeFlowCallbackSilentRenewIframe'
- ).and.returnValue(of({} as CallbackContext));
+ it('calls authorizedImplicitFlowCallback if current flow is not code flow', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ const codeFlowCallbackSilentRenewIframe = vi
+ .spyOn(silentRenewService, 'codeFlowCallbackSilentRenewIframe')
+ .mockReturnValue(of({} as CallbackContext));
const eventData = { detail: 'detail?detail2' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }];
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
- expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledOnceWith(
+ await vi.advanceTimersByTimeAsync(1000);
+ expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledExactlyOnceWith(
['detail', 'detail2'],
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- }));
+ });
- it('calls next on refreshSessionWithIFrameCompleted with callbackcontext', fakeAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- spyOn(
+ it('calls next on refreshSessionWithIFrameCompleted with callbackcontext', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ vi.spyOn(
silentRenewService,
'codeFlowCallbackSilentRenewIframe'
- ).and.returnValue(
+ ).mockReturnValue(
of({ refreshToken: 'callbackContext' } as CallbackContext)
);
const eventData = { detail: 'detail?detail2' } as CustomEvent;
@@ -321,42 +318,42 @@ describe('SilentRenewService ', () => {
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
- }));
+ await vi.advanceTimersByTimeAsync(1000);
+ });
- it('loggs and calls flowsDataService.resetSilentRenewRunning in case of an error', fakeAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- spyOn(
+ it('loggs and calls flowsDataService.resetSilentRenewRunning in case of an error', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ vi.spyOn(
silentRenewService,
'codeFlowCallbackSilentRenewIframe'
- ).and.returnValue(throwError(() => new Error('ERROR')));
- const resetSilentRenewRunningSpy = spyOn(
+ ).mockReturnValue(throwError(() => new Error('ERROR')));
+ const resetSilentRenewRunningSpy = vi.spyOn(
flowsDataService,
'resetSilentRenewRunning'
);
- const logErrorSpy = spyOn(loggerService, 'logError');
+ const logErrorSpy = vi.spyOn(loggerService, 'logError');
const allConfigs = [{ configId: 'configId1' }];
const eventData = { detail: 'detail?detail2' } as CustomEvent;
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
+ await vi.advanceTimersByTimeAsync(1000);
expect(resetSilentRenewRunningSpy).toHaveBeenCalledTimes(1);
expect(logErrorSpy).toHaveBeenCalledTimes(1);
- }));
+ });
- it('calls next on refreshSessionWithIFrameCompleted with null in case of error', fakeAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- spyOn(
+ it('calls next on refreshSessionWithIFrameCompleted with null in case of error', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ vi.spyOn(
silentRenewService,
'codeFlowCallbackSilentRenewIframe'
- ).and.returnValue(throwError(() => new Error('ERROR')));
+ ).mockReturnValue(throwError(() => new Error('ERROR')));
const eventData = { detail: 'detail?detail2' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }];
@@ -368,10 +365,10 @@ describe('SilentRenewService ', () => {
silentRenewService.silentRenewEventHandler(
eventData,
- allConfigs[0],
+ allConfigs[0]!,
allConfigs
);
- tick(1000);
- }));
+ await vi.advanceTimersByTimeAsync(1000);
+ });
});
});
diff --git a/src/iframe/silent-renew.service.ts b/src/iframe/silent-renew.service.ts
index 25c62de..62cdef1 100644
--- a/src/iframe/silent-renew.service.ts
+++ b/src/iframe/silent-renew.service.ts
@@ -1,12 +1,12 @@
import { HttpParams } from '@ngify/http';
-import { inject, Injectable } from 'injection-js';
-import { Observable, Subject, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, Subject, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ImplicitFlowCallbackService } from '../callback/implicit-flow-callback.service';
import { IntervalService } from '../callback/interval.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { FlowsService } from '../flows/flows.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
diff --git a/src/index.ts b/src/index.ts
index 9f7afcf..f35cfe4 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,7 +5,6 @@ export * from './auth-options';
export * from './auth-state/auth-result';
export * from './auth-state/auth-state';
export * from './auth.module';
-export * from './auto-login/auto-login-all-routes.guard';
export * from './auto-login/auto-login-partial-routes.guard';
export * from './config/auth-well-known/auth-well-known-endpoints';
export * from './config/config.service';
@@ -29,3 +28,5 @@ export * from './user-data/userdata-result';
export * from './validation/jwtkeys';
export * from './validation/state-validation-result';
export * from './validation/validation-result';
+export * from './injection';
+export * from './router';
diff --git a/src/injection/convention.ts b/src/injection/convention.ts
new file mode 100644
index 0000000..28947a1
--- /dev/null
+++ b/src/injection/convention.ts
@@ -0,0 +1,7 @@
+import { InjectionToken } from 'injection-js';
+import type { Observable } from 'rxjs';
+
+export const APP_INITIALIZER = new InjectionToken<
+ // biome-ignore lint/suspicious/noConfusingVoidType:
+ readonly (() => void | Observable | Promise)[]
+>('APP_INITIALIZER');
diff --git a/src/injection/index.ts b/src/injection/index.ts
new file mode 100644
index 0000000..73ce5ec
--- /dev/null
+++ b/src/injection/index.ts
@@ -0,0 +1,3 @@
+export { Module } from './module';
+export { APP_INITIALIZER } from './convention';
+export { injectAbstractType } from './inject';
diff --git a/src/injection/inject.ts b/src/injection/inject.ts
new file mode 100644
index 0000000..4ad96bb
--- /dev/null
+++ b/src/injection/inject.ts
@@ -0,0 +1,10 @@
+import { inject } from 'injection-js';
+
+// biome-ignore lint/complexity/noBannedTypes:
+export interface AbstractType extends Function {
+ prototype: T;
+}
+
+export function injectAbstractType(abstractType: AbstractType): T {
+ return inject(abstractType as any);
+}
diff --git a/src/injection/module.ts b/src/injection/module.ts
new file mode 100644
index 0000000..b715030
--- /dev/null
+++ b/src/injection/module.ts
@@ -0,0 +1,4 @@
+import 'reflect-metadata';
+import type { Injector } from 'injection-js';
+
+export type Module = (parentInjector: Injector) => Injector;
diff --git a/src/interceptor/auth.interceptor.spec.ts b/src/interceptor/auth.interceptor.spec.ts
index d363f2f..9250759 100644
--- a/src/interceptor/auth.interceptor.spec.ts
+++ b/src/interceptor/auth.interceptor.spec.ts
@@ -1,19 +1,20 @@
+import { TestBed } from '@/testing';
import {
HTTP_INTERCEPTORS,
HttpClient,
provideHttpClient,
withInterceptors,
withInterceptorsFromDi,
-} from '@angular/common/http';
+} from '@ngify/http';
import {
HttpTestingController,
provideHttpClientTesting,
-} from '@angular/common/http/testing';
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { mockProvider } from '../../test/auto-mock';
+} from '@ngify/http/testing';
+import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service';
import { ConfigurationService } from '../config/config.service';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { AuthInterceptor, authInterceptor } from './auth.interceptor';
import { ClosestMatchingRouteService } from './closest-matching-route.service';
@@ -85,18 +86,22 @@ describe(`AuthHttpInterceptor`, () => {
});
function runTests(): void {
- it('should add an Authorization header when route matches and token is present', waitForAsync(() => {
+ it('should add an Authorization header when route matches and token is present', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
secureRoutes: [actionUrl],
configId: 'configId1',
},
]);
- spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
+ 'thisIsAToken'
+ );
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -108,18 +113,22 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when `secureRoutes` is not given', waitForAsync(() => {
+ it('should not add an Authorization header when `secureRoutes` is not given', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
configId: 'configId1',
},
]);
- spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
+ 'thisIsAToken'
+ );
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -131,20 +140,24 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when no routes configured', waitForAsync(() => {
+ it('should not add an Authorization header when no routes configured', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
secureRoutes: [],
configId: 'configId1',
},
]);
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
- spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
+ 'thisIsAToken'
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -156,19 +169,21 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when no routes configured', waitForAsync(() => {
+ it('should not add an Authorization header when no routes configured', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
secureRoutes: [],
configId: 'configId1',
},
]);
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -180,20 +195,22 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when route is configured but no token is present', waitForAsync(() => {
+ it('should not add an Authorization header when route is configured but no token is present', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
secureRoutes: [actionUrl],
configId: 'configId1',
},
]);
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
- spyOn(authStateService, 'getAccessToken').and.returnValue('');
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('');
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -205,12 +222,14 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when no config is present', waitForAsync(() => {
+ it('should not add an Authorization header when no config is present', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(false);
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ false
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -222,22 +241,24 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should not add an Authorization header when no configured route is matching the request', waitForAsync(() => {
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
+ it('should not add an Authorization header when no configured route is matching the request', async () => {
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
const actionUrl = `https://jsonplaceholder.typicode.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{
secureRoutes: [actionUrl],
configId: 'configId1',
},
]);
- spyOn(
+ vi.spyOn(
closestMatchingRouteService,
'getConfigIdForClosestMatchingRoute'
- ).and.returnValue({
+ ).mockReturnValue({
matchingRoute: null,
matchingConfig: null,
});
@@ -252,18 +273,22 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpTestingController.verify();
- }));
+ });
- it('should add an Authorization header when multiple routes are configured and token is present', waitForAsync(() => {
+ it('should add an Authorization header when multiple routes are configured and token is present', async () => {
const actionUrl = `https://jsonplaceholder.typicode.com/`;
const actionUrl2 = `https://some-other-url.com/`;
- spyOn(configurationService, 'getAllConfigurations').and.returnValue([
+ vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
{ secureRoutes: [actionUrl, actionUrl2], configId: 'configId1' },
]);
- spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
- spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
+ 'thisIsAToken'
+ );
+ vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
+ true
+ );
httpClient.get(actionUrl).subscribe((response) => {
expect(response).toBeTruthy();
@@ -284,6 +309,6 @@ describe(`AuthHttpInterceptor`, () => {
httpRequest.flush('something');
httpRequest2.flush('something');
httpTestingController.verify();
- }));
+ });
}
});
diff --git a/src/interceptor/closest-matching-route.service.spec.ts b/src/interceptor/closest-matching-route.service.spec.ts
index 7cf5581..ecf8746 100644
--- a/src/interceptor/closest-matching-route.service.spec.ts
+++ b/src/interceptor/closest-matching-route.service.spec.ts
@@ -1,6 +1,7 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { ClosestMatchingRouteService } from './closest-matching-route.service';
describe('ClosestMatchingRouteService', () => {
diff --git a/src/logging/logger.service.spec.ts b/src/logging/logger.service.spec.ts
index 7da12b9..30111c9 100644
--- a/src/logging/logger.service.spec.ts
+++ b/src/logging/logger.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { AbstractLoggerService } from './abstract-logger.service';
import { ConsoleLoggerService } from './console-logger.service';
import { LogLevel } from './log-level';
@@ -26,7 +27,7 @@ describe('Logger Service', () => {
describe('logError', () => {
it('should not log error if loglevel is None', () => {
- const spy = spyOn(console, 'error');
+ const spy = vi.spyOn(console, 'error');
loggerService.logError(
{ configId: 'configId1', logLevel: LogLevel.None },
@@ -36,23 +37,25 @@ describe('Logger Service', () => {
});
it('should log error as default if error is string', () => {
- const spy = spyOn(console, 'error');
+ const spy = vi.spyOn(console, 'error');
loggerService.logError({ configId: 'configId1' }, 'some message');
- expect(spy).toHaveBeenCalledOnceWith('[ERROR] configId1 - some message');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ '[ERROR] configId1 - some message'
+ );
});
it('should log error as default if error is object', () => {
- const spy = spyOn(console, 'error');
+ const spy = vi.spyOn(console, 'error');
loggerService.logError({ configId: 'configId1' }, { some: 'message' });
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[ERROR] configId1 - {"some":"message"}'
);
});
it('should always log error with args', () => {
- const spy = spyOn(console, 'error');
+ const spy = vi.spyOn(console, 'error');
loggerService.logError(
{ configId: 'configId1' },
@@ -60,7 +63,7 @@ describe('Logger Service', () => {
'arg1',
'arg2'
);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[ERROR] configId1 - some message',
'arg1',
'arg2'
@@ -70,7 +73,7 @@ describe('Logger Service', () => {
describe('logWarn', () => {
it('should not log if no log level is set (null)', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: undefined },
@@ -80,14 +83,14 @@ describe('Logger Service', () => {
});
it('should not log if no config is given', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning({}, 'some message');
expect(spy).not.toHaveBeenCalled();
});
it('should not log if no log level is set (undefined)', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning({ configId: 'configId1' }, 'some message');
@@ -95,7 +98,7 @@ describe('Logger Service', () => {
});
it('should not log if log level is turned off', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.None },
@@ -105,29 +108,31 @@ describe('Logger Service', () => {
});
it('should log warning when loglevel is Warn and message is string', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.Warn },
'some message'
);
- expect(spy).toHaveBeenCalledOnceWith('[WARN] configId1 - some message');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ '[WARN] configId1 - some message'
+ );
});
it('should log warning when loglevel is Warn and message is object', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.Warn },
{ some: 'message' }
);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[WARN] configId1 - {"some":"message"}'
);
});
it('should log warning when loglevel is Warn with args', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.Warn },
@@ -135,7 +140,7 @@ describe('Logger Service', () => {
'arg1',
'arg2'
);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[WARN] configId1 - some message',
'arg1',
'arg2'
@@ -143,17 +148,19 @@ describe('Logger Service', () => {
});
it('should log warning when loglevel is Debug', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.Debug },
'some message'
);
- expect(spy).toHaveBeenCalledOnceWith('[WARN] configId1 - some message');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ '[WARN] configId1 - some message'
+ );
});
it('should not log warning when loglevel is error', () => {
- const spy = spyOn(console, 'warn');
+ const spy = vi.spyOn(console, 'warn');
loggerService.logWarning(
{ configId: 'configId1', logLevel: LogLevel.Error },
@@ -165,7 +172,7 @@ describe('Logger Service', () => {
describe('logDebug', () => {
it('should not log if no log level is set (null)', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: undefined },
@@ -175,14 +182,14 @@ describe('Logger Service', () => {
});
it('should not log if no log level is set (undefined)', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug({ configId: 'configId1' }, 'some message');
expect(spy).not.toHaveBeenCalled();
});
it('should not log if log level is turned off', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.None },
@@ -192,29 +199,31 @@ describe('Logger Service', () => {
});
it('should log when loglevel is Debug and value is string', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.Debug },
'some message'
);
- expect(spy).toHaveBeenCalledOnceWith('[DEBUG] configId1 - some message');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ '[DEBUG] configId1 - some message'
+ );
});
it('should log when loglevel is Debug and value is object', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.Debug },
{ some: 'message' }
);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[DEBUG] configId1 - {"some":"message"}'
);
});
it('should log when loglevel is Debug with args', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.Debug },
@@ -222,7 +231,7 @@ describe('Logger Service', () => {
'arg1',
'arg2'
);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'[DEBUG] configId1 - some message',
'arg1',
'arg2'
@@ -230,7 +239,7 @@ describe('Logger Service', () => {
});
it('should not log when loglevel is Warn', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.Warn },
@@ -240,7 +249,7 @@ describe('Logger Service', () => {
});
it('should not log when loglevel is error', () => {
- const spy = spyOn(console, 'debug');
+ const spy = vi.spyOn(console, 'debug');
loggerService.logDebug(
{ configId: 'configId1', logLevel: LogLevel.Error },
diff --git a/src/logging/logger.service.ts b/src/logging/logger.service.ts
index b1f29d6..3e5d251 100644
--- a/src/logging/logger.service.ts
+++ b/src/logging/logger.service.ts
@@ -1,11 +1,14 @@
-import { inject, Injectable } from 'injection-js';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import { Injectable } from 'injection-js';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import { injectAbstractType } from '../injection/inject';
import { AbstractLoggerService } from './abstract-logger.service';
import { LogLevel } from './log-level';
@Injectable()
export class LoggerService {
- private readonly abstractLoggerService = inject(AbstractLoggerService);
+ private readonly abstractLoggerService = injectAbstractType(
+ AbstractLoggerService
+ );
logError(
configuration: OpenIdConfiguration,
diff --git a/src/login/login.service.spec.ts b/src/login/login.service.spec.ts
index bf538bd..cc98702 100644
--- a/src/login/login.service.spec.ts
+++ b/src/login/login.service.spec.ts
@@ -1,9 +1,10 @@
+import { TestBed } from '@/testing';
import { CommonModule } from '@angular/common';
-import { TestBed, waitForAsync } from '@angular/core/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { vi } from 'vitest';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
-import { LoginResponse } from './login-response';
+import { mockProvider } from '../testing/mock';
+import type { LoginResponse } from './login-response';
import { LoginService } from './login.service';
import { ParLoginService } from './par/par-login.service';
import { PopUpLoginService } from './popup/popup-login.service';
@@ -48,8 +49,8 @@ describe('LoginService', () => {
describe('login', () => {
it('calls parLoginService loginPar if usePushedAuthorisationRequests is true', () => {
const config = { usePushedAuthorisationRequests: true };
- const loginParSpy = spyOn(parLoginService, 'loginPar');
- const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
+ const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
+ const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
service.login(config);
@@ -59,8 +60,8 @@ describe('LoginService', () => {
it('calls standardLoginService loginStandard if usePushedAuthorisationRequests is false', () => {
const config = { usePushedAuthorisationRequests: false };
- const loginParSpy = spyOn(parLoginService, 'loginPar');
- const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
+ const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
+ const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
service.login(config);
@@ -71,7 +72,7 @@ describe('LoginService', () => {
it('stores the customParams to the storage if customParams are given', () => {
// arrange
const config = { usePushedAuthorisationRequests: false };
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
@@ -79,7 +80,7 @@ describe('LoginService', () => {
service.login(config, authOptions);
- expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
+ expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsAuthRequest',
{ custom: 'params' },
config
@@ -89,8 +90,8 @@ describe('LoginService', () => {
it("should throw error if configuration is null and doesn't call loginPar or loginStandard", () => {
// arrange
const config = null;
- const loginParSpy = spyOn(parLoginService, 'loginPar');
- const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
+ const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
+ const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
const authOptions = { customParams: { custom: 'params' } };
// act
@@ -106,17 +107,15 @@ describe('LoginService', () => {
});
describe('loginWithPopUp', () => {
- it('calls parLoginService loginWithPopUpPar if usePushedAuthorisationRequests is true', waitForAsync(() => {
+ it('calls parLoginService loginWithPopUpPar if usePushedAuthorisationRequests is true', async () => {
// arrange
const config = { usePushedAuthorisationRequests: true };
- const loginWithPopUpPar = spyOn(
- parLoginService,
- 'loginWithPopUpPar'
- ).and.returnValue(of({} as LoginResponse));
- const loginWithPopUpStandardSpy = spyOn(
- popUpLoginService,
- 'loginWithPopUpStandard'
- ).and.returnValue(of({} as LoginResponse));
+ const loginWithPopUpPar = vi
+ .spyOn(parLoginService, 'loginWithPopUpPar')
+ .mockReturnValue(of({} as LoginResponse));
+ const loginWithPopUpStandardSpy = vi
+ .spyOn(popUpLoginService, 'loginWithPopUpStandard')
+ .mockReturnValue(of({} as LoginResponse));
// act
service.loginWithPopUp(config, [config]).subscribe(() => {
@@ -124,19 +123,17 @@ describe('LoginService', () => {
expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', waitForAsync(() => {
+ it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', async () => {
// arrange
const config = { usePushedAuthorisationRequests: false };
- const loginWithPopUpPar = spyOn(
- parLoginService,
- 'loginWithPopUpPar'
- ).and.returnValue(of({} as LoginResponse));
- const loginWithPopUpStandardSpy = spyOn(
- popUpLoginService,
- 'loginWithPopUpStandard'
- ).and.returnValue(of({} as LoginResponse));
+ const loginWithPopUpPar = vi
+ .spyOn(parLoginService, 'loginWithPopUpPar')
+ .mockReturnValue(of({} as LoginResponse));
+ const loginWithPopUpStandardSpy = vi
+ .spyOn(popUpLoginService, 'loginWithPopUpStandard')
+ .mockReturnValue(of({} as LoginResponse));
// act
service.loginWithPopUp(config, [config]).subscribe(() => {
@@ -144,46 +141,44 @@ describe('LoginService', () => {
expect(loginWithPopUpPar).not.toHaveBeenCalled();
expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
});
- }));
+ });
- it('stores the customParams to the storage if customParams are given', waitForAsync(() => {
+ it('stores the customParams to the storage if customParams are given', async () => {
// arrange
const config = { usePushedAuthorisationRequests: false };
- const storagePersistenceServiceSpy = spyOn(
+ const storagePersistenceServiceSpy = vi.spyOn(
storagePersistenceService,
'write'
);
const authOptions = { customParams: { custom: 'params' } };
- spyOn(popUpLoginService, 'loginWithPopUpStandard').and.returnValue(
+ vi.spyOn(popUpLoginService, 'loginWithPopUpStandard').mockReturnValue(
of({} as LoginResponse)
);
// act
service.loginWithPopUp(config, [config], authOptions).subscribe(() => {
// assert
- expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
+ expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsAuthRequest',
{ custom: 'params' },
config
);
});
- }));
+ });
it('returns error if there is already a popup open', () => {
// arrange
const config = { usePushedAuthorisationRequests: false };
const authOptions = { customParams: { custom: 'params' } };
- const loginWithPopUpPar = spyOn(
- parLoginService,
- 'loginWithPopUpPar'
- ).and.returnValue(of({} as LoginResponse));
- const loginWithPopUpStandardSpy = spyOn(
- popUpLoginService,
- 'loginWithPopUpStandard'
- ).and.returnValue(of({} as LoginResponse));
+ const loginWithPopUpPar = vi
+ .spyOn(parLoginService, 'loginWithPopUpPar')
+ .mockReturnValue(of({} as LoginResponse));
+ const loginWithPopUpStandardSpy = vi
+ .spyOn(popUpLoginService, 'loginWithPopUpStandard')
+ .mockReturnValue(of({} as LoginResponse));
- spyOn(popUpService, 'isCurrentlyInPopup').and.returnValue(true);
+ vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
// act
service
diff --git a/src/login/login.service.ts b/src/login/login.service.ts
index d88d102..709145b 100644
--- a/src/login/login.service.ts
+++ b/src/login/login.service.ts
@@ -1,12 +1,12 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable, of } from 'rxjs';
-import { AuthOptions } from '../auth-options';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of } from 'rxjs';
+import type { AuthOptions } from '../auth-options';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
-import { LoginResponse } from './login-response';
+import type { LoginResponse } from './login-response';
import { ParLoginService } from './par/par-login.service';
import { PopUpLoginService } from './popup/popup-login.service';
-import { PopupOptions } from './popup/popup-options';
+import type { PopupOptions } from './popup/popup-options';
import { PopUpService } from './popup/popup.service';
import { StandardLoginService } from './standard/standard-login.service';
@@ -45,12 +45,9 @@ export class LoginService {
}
if (usePushedAuthorisationRequests) {
- return this.parLoginService.loginPar(configuration, authOptions);
+ this.parLoginService.loginPar(configuration, authOptions);
} else {
- return this.standardLoginService.loginStandard(
- configuration,
- authOptions
- );
+ this.standardLoginService.loginStandard(configuration, authOptions);
}
}
diff --git a/src/login/par/par-login.service.spec.ts b/src/login/par/par-login.service.spec.ts
index 02e0a99..c41831e 100644
--- a/src/login/par/par-login.service.spec.ts
+++ b/src/login/par/par-login.service.spec.ts
@@ -1,17 +1,18 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { RedirectService } from '../../utils/redirect/redirect.service';
import { UrlService } from '../../utils/url/url.service';
-import { LoginResponse } from '../login-response';
-import { PopupResult } from '../popup/popup-result';
+import type { LoginResponse } from '../login-response';
+import type { PopupResult } from '../popup/popup-result';
import { PopUpService } from '../popup/popup.service';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
import { ParLoginService } from './par-login.service';
-import { ParResponse } from './par-response';
+import type { ParResponse } from './par-response';
import { ParService } from './par.service';
describe('ParLoginService', () => {
@@ -60,33 +61,33 @@ describe('ParLoginService', () => {
});
describe('loginPar', () => {
- it('does nothing if it has an invalid response type', waitForAsync(() => {
- spyOn(
+ it('does nothing if it has an invalid response type', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(false);
- const loggerSpy = spyOn(loggerService, 'logError');
+ ).mockReturnValue(false);
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const result = service.loginPar({});
expect(result).toBeUndefined();
expect(loggerSpy).toHaveBeenCalled();
- }));
+ });
- it('calls parService.postParRequest without custom params when no custom params are passed', waitForAsync(() => {
- spyOn(
+ it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- const spy = spyOn(parService, 'postParRequest').and.returnValue(
- of({ requestUri: 'requestUri' } as ParResponse)
- );
+ const spy = vi
+ .spyOn(parService, 'postParRequest')
+ .mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
const result = service.loginPar({
authWellknownEndpointUrl: 'authWellknownEndpoint',
@@ -95,69 +96,69 @@ describe('ParLoginService', () => {
expect(result).toBeUndefined();
expect(spy).toHaveBeenCalled();
- }));
+ });
- it('calls parService.postParRequest with custom params when custom params are passed', waitForAsync(() => {
- spyOn(
+ it('calls parService.postParRequest with custom params when custom params are passed', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- const spy = spyOn(parService, 'postParRequest').and.returnValue(
- of({ requestUri: 'requestUri' } as ParResponse)
- );
+ const spy = vi
+ .spyOn(parService, 'postParRequest')
+ .mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
const result = service.loginPar(config, {
customParams: { some: 'thing' },
});
expect(result).toBeUndefined();
- expect(spy).toHaveBeenCalledOnceWith(config, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { some: 'thing' },
});
- }));
+ });
- it('returns undefined and logs error when no url could be created', waitForAsync(() => {
- spyOn(
+ it('returns undefined and logs error when no url could be created', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('');
- const spy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
+ const spy = vi.spyOn(loggerService, 'logError');
const result = service.loginPar(config);
expect(result).toBeUndefined();
expect(spy).toHaveBeenCalledTimes(1);
- }));
+ });
- it('calls redirect service redirectTo when url could be created', waitForAsync(() => {
- spyOn(
+ it('calls redirect service redirectTo when url could be created', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
@@ -165,42 +166,46 @@ describe('ParLoginService', () => {
const authOptions = {};
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
- const spy = spyOn(redirectService, 'redirectTo');
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
+ 'some-par-url'
+ );
+ const spy = vi.spyOn(redirectService, 'redirectTo');
service.loginPar(config, authOptions);
- expect(spy).toHaveBeenCalledOnceWith('some-par-url');
- }));
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
+ });
- it('calls urlHandler when URL is passed', waitForAsync(() => {
- spyOn(
+ it('calls urlHandler when URL is passed', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
- const redirectToSpy = spyOn(redirectService, 'redirectTo');
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
+ 'some-par-url'
+ );
+ const redirectToSpy = vi.spyOn(redirectService, 'redirectTo');
const spy = jasmine.createSpy();
const urlHandler = (url: any): void => {
spy(url);
@@ -208,18 +213,18 @@ describe('ParLoginService', () => {
service.loginPar(config, { urlHandler });
- expect(spy).toHaveBeenCalledOnceWith('some-par-url');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
expect(redirectToSpy).not.toHaveBeenCalled();
- }));
+ });
});
describe('loginWithPopUpPar', () => {
- it('does nothing if it has an invalid response type', waitForAsync(() => {
- spyOn(
+ it('does nothing if it has an invalid response type', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(false);
- const loggerSpy = spyOn(loggerService, 'logError');
+ ).mockReturnValue(false);
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = {};
const allConfigs = [config];
@@ -229,27 +234,27 @@ describe('ParLoginService', () => {
expect(err.message).toBe('Invalid response type!');
},
});
- }));
+ });
- it('calls parService.postParRequest without custom params when no custom params are passed', waitForAsync(() => {
- spyOn(
+ it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- const spy = spyOn(parService, 'postParRequest').and.returnValue(
- of({ requestUri: 'requestUri' } as ParResponse)
- );
+ const spy = vi
+ .spyOn(parService, 'postParRequest')
+ .mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
service.loginWithPopUpPar(config, allConfigs).subscribe({
error: (err) => {
@@ -259,27 +264,27 @@ describe('ParLoginService', () => {
);
},
});
- }));
+ });
- it('calls parService.postParRequest with custom params when custom params are passed', waitForAsync(() => {
- spyOn(
+ it('calls parService.postParRequest with custom params when custom params are passed', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- const spy = spyOn(parService, 'postParRequest').and.returnValue(
- of({ requestUri: 'requestUri' } as ParResponse)
- );
+ const spy = vi
+ .spyOn(parService, 'postParRequest')
+ .mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
service
.loginWithPopUpPar(config, allConfigs, {
@@ -287,7 +292,7 @@ describe('ParLoginService', () => {
})
.subscribe({
error: (err) => {
- expect(spy).toHaveBeenCalledOnceWith(config, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { some: 'thing' },
});
expect(err.message).toBe(
@@ -295,29 +300,29 @@ describe('ParLoginService', () => {
);
},
});
- }));
+ });
- it('returns undefined and logs error when no URL could be created', waitForAsync(() => {
- spyOn(
+ it('returns undefined and logs error when no URL could be created', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('');
- const spy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
+ const spy = vi.spyOn(loggerService, 'logError');
service
.loginWithPopUpPar(config, allConfigs, {
@@ -331,46 +336,52 @@ describe('ParLoginService', () => {
expect(spy).toHaveBeenCalledTimes(1);
},
});
- }));
+ });
- it('calls popupService openPopUp when URL could be created', waitForAsync(() => {
- spyOn(
+ it('calls popupService openPopUp when URL could be created', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
- spyOn(checkAuthService, 'checkAuth').and.returnValue(
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
+ 'some-par-url'
+ );
+ vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
of({} as LoginResponse)
);
- spyOnProperty(popupService, 'result$').and.returnValue(
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult)
);
- const spy = spyOn(popupService, 'openPopUp');
+ const spy = vi.spyOn(popupService, 'openPopUp');
service.loginWithPopUpPar(config, allConfigs).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-par-url', undefined, config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'some-par-url',
+ undefined,
+ config
+ );
});
- }));
+ });
- it('returns correct properties if URL is received', waitForAsync(() => {
- spyOn(
+ it('returns correct properties if URL is received', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
@@ -378,34 +389,40 @@ describe('ParLoginService', () => {
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
-
- const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
- of({
- isAuthenticated: true,
- configId: 'configId1',
- idToken: '',
- userData: { any: 'userData' },
- accessToken: 'anyAccessToken',
- })
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
+ 'some-par-url'
);
+
+ const checkAuthSpy = vi
+ .spyOn(checkAuthService, 'checkAuth')
+ .mockReturnValue(
+ of({
+ isAuthenticated: true,
+ configId: 'configId1',
+ idToken: '',
+ userData: { any: 'userData' },
+ accessToken: 'anyAccessToken',
+ })
+ );
const popupResult: PopupResult = {
userClosed: false,
receivedUrl: 'someUrl',
};
- spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
+ of(popupResult)
+ );
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
- expect(checkAuthSpy).toHaveBeenCalledOnceWith(
+ expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
config,
allConfigs,
'someUrl'
@@ -419,13 +436,13 @@ describe('ParLoginService', () => {
accessToken: 'anyAccessToken',
});
});
- }));
+ });
- it('returns correct properties if popup was closed by user', waitForAsync(() => {
- spyOn(
+ it('returns correct properties if popup was closed by user', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
@@ -433,20 +450,24 @@ describe('ParLoginService', () => {
};
const allConfigs = [config];
- spyOn(
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ ).mockReturnValue(of({}));
- spyOn(parService, 'postParRequest').and.returnValue(
+ vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
- spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
+ vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
+ 'some-par-url'
+ );
- const checkAuthSpy = spyOn(checkAuthService, 'checkAuth');
+ const checkAuthSpy = vi.spyOn(checkAuthService, 'checkAuth');
const popupResult = { userClosed: true } as PopupResult;
- spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
+ of(popupResult)
+ );
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
expect(checkAuthSpy).not.toHaveBeenCalled();
@@ -459,6 +480,6 @@ describe('ParLoginService', () => {
accessToken: '',
});
});
- }));
+ });
});
});
diff --git a/src/login/par/par-login.service.ts b/src/login/par/par-login.service.ts
index 8d34d9a..7019d35 100644
--- a/src/login/par/par-login.service.ts
+++ b/src/login/par/par-login.service.ts
@@ -1,19 +1,19 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of, throwError } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
-import { AuthOptions } from '../../auth-options';
+import type { AuthOptions } from '../../auth-options';
import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { LoggerService } from '../../logging/logger.service';
import { RedirectService } from '../../utils/redirect/redirect.service';
import { UrlService } from '../../utils/url/url.service';
-import { LoginResponse } from '../login-response';
-import { PopupOptions } from '../popup/popup-options';
-import { PopupResult } from '../popup/popup-result';
+import type { LoginResponse } from '../login-response';
+import type { PopupOptions } from '../popup/popup-options';
+import type { PopupResult } from '../popup/popup-result';
import { PopUpService } from '../popup/popup.service';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
-import { ParResponse } from './par-response';
+import type { ParResponse } from './par-response';
import { ParService } from './par.service';
@Injectable()
diff --git a/src/login/par/par.service.spec.ts b/src/login/par/par.service.spec.ts
index 7a222d7..4e1faed 100644
--- a/src/login/par/par.service.spec.ts
+++ b/src/login/par/par.service.spec.ts
@@ -1,11 +1,12 @@
-import { HttpHeaders } from '@angular/common/http';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { HttpHeaders } from '@ngify/http';
import { of, throwError } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
-import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
+import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
+import { mockProvider } from '../../testing/mock';
import { UrlService } from '../../utils/url/url.service';
import { ParService } from './par.service';
@@ -40,13 +41,15 @@ describe('ParService', () => {
});
describe('postParRequest', () => {
- it('throws error if authWellKnownEndPoints does not exist in storage', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('throws error if authWellKnownEndPoints does not exist in storage', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of(null)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => null
+ );
service.postParRequest({ configId: 'configId1' }).subscribe({
error: (err) => {
expect(err.message).toBe(
@@ -54,15 +57,17 @@ describe('ParService', () => {
);
},
});
- }));
+ });
- it('throws error if par endpoint does not exist in storage', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('throws error if par endpoint does not exist in storage', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of(null)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ some: 'thing' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ some: 'thing' })
+ );
service.postParRequest({ configId: 'configId1' }).subscribe({
error: (err) => {
expect(err.message).toBe(
@@ -70,77 +75,87 @@ describe('ParService', () => {
);
},
});
- }));
+ });
- it('calls data service with correct params', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('calls data service with correct params', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url123')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
- const dataServiceSpy = spyOn(dataService, 'post').and.returnValue(of({}));
+ const dataServiceSpy = vi
+ .spyOn(dataService, 'post')
+ .mockReturnValue(of({}));
service.postParRequest({ configId: 'configId1' }).subscribe(() => {
- expect(dataServiceSpy).toHaveBeenCalledOnceWith(
+ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
'parEndpoint',
'some-url123',
{ configId: 'configId1' },
- jasmine.any(HttpHeaders)
+ expect.any(HttpHeaders)
);
});
- }));
+ });
- it('Gives back correct object properties', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('Gives back correct object properties', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url456')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
- spyOn(dataService, 'post').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
+ vi.spyOn(dataService, 'post').mockReturnValue(
of({ expires_in: 123, request_uri: 'request_uri' })
);
service.postParRequest({ configId: 'configId1' }).subscribe((result) => {
expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
});
- }));
+ });
- it('throws error if data service has got an error', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('throws error if data service has got an error', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url789')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
- spyOn(dataService, 'post').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
+ vi.spyOn(dataService, 'post').mockReturnValue(
throwError(() => new Error('ERROR'))
);
- const loggerSpy = spyOn(loggerService, 'logError');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
service.postParRequest({ configId: 'configId1' }).subscribe({
error: (err) => {
expect(err.message).toBe(
'There was an error on ParService postParRequest'
);
- expect(loggerSpy).toHaveBeenCalledOnceWith(
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'There was an error on ParService postParRequest',
- jasmine.any(Error)
+ expect.any(Error)
);
},
});
- }));
+ });
- it('should retry once', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('should retry once', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url456')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
- spyOn(dataService, 'post').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('ERROR')),
of({ expires_in: 123, request_uri: 'request_uri' })
@@ -153,16 +168,18 @@ describe('ParService', () => {
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
},
});
- }));
+ });
- it('should retry twice', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('should retry twice', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url456')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
- spyOn(dataService, 'post').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('ERROR')),
throwError(() => new Error('ERROR')),
@@ -176,16 +193,18 @@ describe('ParService', () => {
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
},
});
- }));
+ });
- it('should fail after three tries', waitForAsync(() => {
- spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
+ it('should fail after three tries', async () => {
+ vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
of('some-url456')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({ parEndpoint: 'parEndpoint' });
- spyOn(dataService, 'post').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({ parEndpoint: 'parEndpoint' })
+ );
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('ERROR')),
throwError(() => new Error('ERROR')),
@@ -199,6 +218,6 @@ describe('ParService', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
});
diff --git a/src/login/popup/popup-login.service.spec.ts b/src/login/popup/popup-login.service.spec.ts
index 9d8116e..ee27439 100644
--- a/src/login/popup/popup-login.service.spec.ts
+++ b/src/login/popup/popup-login.service.spec.ts
@@ -1,15 +1,16 @@
+import { TestBed } from '@/testing';
import { CommonModule } from '@angular/common';
-import { TestBed, waitForAsync } from '@angular/core/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { UrlService } from '../../utils/url/url.service';
-import { LoginResponse } from '../login-response';
+import type { LoginResponse } from '../login-response';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
import { PopUpLoginService } from './popup-login.service';
-import { PopupResult } from './popup-result';
+import type { PopupResult } from './popup-result';
import { PopUpService } from './popup.service';
describe('PopUpLoginService', () => {
@@ -53,14 +54,14 @@ describe('PopUpLoginService', () => {
});
describe('loginWithPopUpStandard', () => {
- it('does nothing if it has an invalid response type', waitForAsync(() => {
+ it('does nothing if it has an invalid response type', async () => {
const config = { responseType: 'stubValue' };
- spyOn(
+ vi.spyOn(
responseTypValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(false);
- const loggerSpy = spyOn(loggerService, 'logError');
+ ).mockReturnValue(false);
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
popUpLoginService.loginWithPopUpStandard(config, [config]).subscribe({
error: (err) => {
@@ -68,27 +69,27 @@ describe('PopUpLoginService', () => {
expect(err.message).toBe('Invalid response type!');
},
});
- }));
+ });
- it('calls urlService.getAuthorizeUrl() if everything fits', waitForAsync(() => {
+ it('calls urlService.getAuthorizeUrl() if everything fits', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOnProperty(popupService, 'result$').and.returnValue(
+ ).mockReturnValue(of({}));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult)
);
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- spyOn(checkAuthService, 'checkAuth').and.returnValue(
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
of({} as LoginResponse)
);
@@ -97,74 +98,78 @@ describe('PopUpLoginService', () => {
.subscribe(() => {
expect(urlService.getAuthorizeUrl).toHaveBeenCalled();
});
- }));
+ });
- it('opens popup if everything fits', waitForAsync(() => {
+ it('opens popup if everything fits', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- spyOnProperty(popupService, 'result$').and.returnValue(
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult)
);
- spyOn(checkAuthService, 'checkAuth').and.returnValue(
+ vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
of({} as LoginResponse)
);
- const popupSpy = spyOn(popupService, 'openPopUp');
+ const popupSpy = vi.spyOn(popupService, 'openPopUp');
popUpLoginService
.loginWithPopUpStandard(config, [config])
.subscribe(() => {
expect(popupSpy).toHaveBeenCalled();
});
- }));
+ });
- it('returns three properties when popupservice received an url', waitForAsync(() => {
+ it('returns three properties when popupservice received an url', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- spyOn(popupService, 'openPopUp');
- const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
- of({
- isAuthenticated: true,
- configId: 'configId1',
- idToken: '',
- userData: { any: 'userData' },
- accessToken: 'anyAccessToken',
- })
- );
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ vi.spyOn(popupService, 'openPopUp');
+ const checkAuthSpy = vi
+ .spyOn(checkAuthService, 'checkAuth')
+ .mockReturnValue(
+ of({
+ isAuthenticated: true,
+ configId: 'configId1',
+ idToken: '',
+ userData: { any: 'userData' },
+ accessToken: 'anyAccessToken',
+ })
+ );
const popupResult: PopupResult = {
userClosed: false,
receivedUrl: 'someUrl',
};
- spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
+ of(popupResult)
+ );
popUpLoginService
.loginWithPopUpStandard(config, [config])
.subscribe((result) => {
- expect(checkAuthSpy).toHaveBeenCalledOnceWith(
+ expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
config,
[config],
'someUrl'
@@ -178,31 +183,33 @@ describe('PopUpLoginService', () => {
accessToken: 'anyAccessToken',
});
});
- }));
+ });
- it('returns two properties if popup was closed by user', waitForAsync(() => {
+ it('returns two properties if popup was closed by user', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
configId: 'configId1',
};
- spyOn(
+ vi.spyOn(
responseTypValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- spyOn(popupService, 'openPopUp');
- const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
- of({} as LoginResponse)
- );
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ vi.spyOn(popupService, 'openPopUp');
+ const checkAuthSpy = vi
+ .spyOn(checkAuthService, 'checkAuth')
+ .mockReturnValue(of({} as LoginResponse));
const popupResult = { userClosed: true } as PopupResult;
- spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
+ vi.spyOnProperty(popupService, 'result$').mockReturnValue(
+ of(popupResult)
+ );
popUpLoginService
.loginWithPopUpStandard(config, [config])
@@ -217,6 +224,6 @@ describe('PopUpLoginService', () => {
accessToken: '',
});
});
- }));
+ });
});
});
diff --git a/src/login/popup/popup-login.service.ts b/src/login/popup/popup-login.service.ts
index 9a47674..c6411df 100644
--- a/src/login/popup/popup-login.service.ts
+++ b/src/login/popup/popup-login.service.ts
@@ -1,16 +1,16 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of, throwError } from 'rxjs';
import { switchMap, take, tap } from 'rxjs/operators';
-import { AuthOptions } from '../../auth-options';
+import type { AuthOptions } from '../../auth-options';
import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { LoggerService } from '../../logging/logger.service';
import { UrlService } from '../../utils/url/url.service';
-import { LoginResponse } from '../login-response';
+import type { LoginResponse } from '../login-response';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
-import { PopupOptions } from './popup-options';
-import { PopupResult } from './popup-result';
+import type { PopupOptions } from './popup-options';
+import type { PopupResult } from './popup-result';
import { PopUpService } from './popup.service';
@Injectable()
diff --git a/src/login/popup/popup.service.spec.ts b/src/login/popup/popup.service.spec.ts
index 27d714e..d28810a 100644
--- a/src/login/popup/popup.service.spec.ts
+++ b/src/login/popup/popup.service.spec.ts
@@ -1,9 +1,10 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import { TestBed, fakeAsync, tick } from '@/testing';
+import { vi } from 'vitest';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
-import { PopupResult } from './popup-result';
+import { mockProvider } from '../../testing/mock';
+import type { PopupResult } from './popup-result';
import { PopUpService } from './popup.service';
describe('PopUpService', () => {
@@ -18,9 +19,6 @@ describe('PopUpService', () => {
mockProvider(LoggerService),
],
});
- });
-
- beforeEach(() => {
storagePersistenceService = TestBed.inject(StoragePersistenceService);
loggerService = TestBed.inject(LoggerService);
popUpService = TestBed.inject(PopUpService);
@@ -51,13 +49,13 @@ describe('PopUpService', () => {
describe('isCurrentlyInPopup', () => {
it('returns false if can not access Session Storage', () => {
// arrange
- spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
+ vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
false
);
- spyOnProperty(popUpService as any, 'windowInternal').and.returnValue({
+ vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window,
});
- spyOn(storagePersistenceService, 'read').and.returnValue({
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
popupauth: true,
});
const config = {} as OpenIdConfiguration;
@@ -71,10 +69,10 @@ describe('PopUpService', () => {
it('returns false if window has no opener', () => {
// arrange
- spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
+ vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
true
);
- spyOn(storagePersistenceService, 'read').and.returnValue({
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
popupauth: true,
});
const config = {} as OpenIdConfiguration;
@@ -88,13 +86,13 @@ describe('PopUpService', () => {
it('returns true if isCurrentlyInPopup', () => {
// arrange
- spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
+ vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
true
);
- spyOnProperty(popUpService as any, 'windowInternal').and.returnValue({
+ vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window,
});
- spyOn(storagePersistenceService, 'read').and.returnValue({
+ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
popupauth: true,
});
const config = {} as OpenIdConfiguration;
@@ -108,7 +106,7 @@ describe('PopUpService', () => {
});
describe('result$', () => {
- it('emits when internal subject is called', waitForAsync(() => {
+ it('emits when internal subject is called', async () => {
const popupResult: PopupResult = {
userClosed: false,
receivedUrl: 'some-url1111',
@@ -119,62 +117,62 @@ describe('PopUpService', () => {
});
(popUpService as any).resultInternal$.next(popupResult);
- }));
+ });
});
describe('openPopup', () => {
- it('popup opens with parameters and default options', waitForAsync(() => {
+ it('popup opens with parameters and default options', async () => {
// arrange
- const popupSpy = spyOn(window, 'open').and.callFake(
+ const popupSpy = vi.spyOn(window, 'open').and.callFake(
() =>
({
closed: true,
close: () => undefined,
- } as Window)
+ }) as Window
);
// act
popUpService.openPopUp('url', {}, { configId: 'configId1' });
// assert
- expect(popupSpy).toHaveBeenCalledOnceWith(
+ expect(popupSpy).toHaveBeenCalledExactlyOnceWith(
'url',
'_blank',
- jasmine.any(String)
+ expect.any(String)
);
- }));
+ });
- it('popup opens with parameters and passed options', waitForAsync(() => {
+ it('popup opens with parameters and passed options', async () => {
// arrange
- const popupSpy = spyOn(window, 'open').and.callFake(
+ const popupSpy = vi.spyOn(window, 'open').and.callFake(
() =>
({
closed: true,
close: () => undefined,
- } as Window)
+ }) as Window
);
// act
popUpService.openPopUp('url', { width: 100 }, { configId: 'configId1' });
// assert
- expect(popupSpy).toHaveBeenCalledOnceWith(
+ expect(popupSpy).toHaveBeenCalledExactlyOnceWith(
'url',
'_blank',
- jasmine.any(String)
+ expect.any(String)
);
- }));
+ });
it('logs error and return if popup could not be opened', () => {
// arrange
- spyOn(window, 'open').and.callFake(() => null);
- const loggerSpy = spyOn(loggerService, 'logError');
+ vi.spyOn(window, 'open').mockImplementation(() => null);
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
// act
popUpService.openPopUp('url', { width: 100 }, { configId: 'configId1' });
// assert
- expect(loggerSpy).toHaveBeenCalledOnceWith(
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' },
'Could not open popup'
);
@@ -191,21 +189,21 @@ describe('PopUpService', () => {
close: () => undefined,
} as Window;
- spyOn(window, 'open').and.returnValue(popup);
+ vi.spyOn(window, 'open').mockReturnValue(popup);
- cleanUpSpy = spyOn(popUpService as any, 'cleanUp').and.callThrough();
+ cleanUpSpy = vi.spyOn(popUpService as any, 'cleanUp')();
popupResult = {} as PopupResult;
popUpService.result$.subscribe((result) => (popupResult = result));
});
- it('message received with data', fakeAsync(() => {
+ it('message received with data', async () => {
let listener: (event: MessageEvent) => void = () => {
return;
};
- spyOn(window, 'addEventListener').and.callFake(
+ vi.spyOn(window, 'addEventListener').and.callFake(
(_: any, func: any) => (listener = func)
);
@@ -222,20 +220,20 @@ describe('PopUpService', () => {
userClosed: false,
receivedUrl: 'some-url1111',
});
- expect(cleanUpSpy).toHaveBeenCalledOnceWith(listener, {
+ expect(cleanUpSpy).toHaveBeenCalledExactlyOnceWith(listener, {
configId: 'configId1',
});
- }));
+ });
- it('message received without data does return but cleanup does not throw event', fakeAsync(() => {
+ it('message received without data does return but cleanup does not throw event', async () => {
let listener: (event: MessageEvent) => void = () => {
return;
};
- spyOn(window, 'addEventListener').and.callFake(
+ vi.spyOn(window, 'addEventListener').and.callFake(
(_: any, func: any) => (listener = func)
);
- const nextSpy = spyOn((popUpService as any).resultInternal$, 'next');
+ const nextSpy = vi.spyOn((popUpService as any).resultInternal$, 'next');
popUpService.openPopUp('url', {}, { configId: 'configId1' });
@@ -249,9 +247,9 @@ describe('PopUpService', () => {
expect(popupResult).toEqual({} as PopupResult);
expect(cleanUpSpy).toHaveBeenCalled();
expect(nextSpy).not.toHaveBeenCalled();
- }));
+ });
- it('user closed', fakeAsync(() => {
+ it('user closed', async () => {
popUpService.openPopUp('url', undefined, { configId: 'configId1' });
expect(popupResult).toEqual({} as PopupResult);
@@ -266,48 +264,48 @@ describe('PopUpService', () => {
receivedUrl: '',
} as PopupResult);
expect(cleanUpSpy).toHaveBeenCalled();
- }));
+ });
});
});
describe('sendMessageToMainWindow', () => {
- it('does nothing if window.opener is null', waitForAsync(() => {
+ it('does nothing if window.opener is null', async () => {
// arrange
- spyOnProperty(window, 'opener').and.returnValue(null);
+ vi.spyOnProperty(window, 'opener').mockReturnValue(null);
- const sendMessageSpy = spyOn(popUpService as any, 'sendMessage');
+ const sendMessageSpy = vi.spyOn(popUpService as any, 'sendMessage');
// act
popUpService.sendMessageToMainWindow('', {});
// assert
expect(sendMessageSpy).not.toHaveBeenCalled();
- }));
+ });
- it('calls postMessage when window opener is given', waitForAsync(() => {
+ it('calls postMessage when window opener is given', async () => {
// arrange
- spyOnProperty(window, 'opener').and.returnValue({
+ vi.spyOnProperty(window, 'opener').mockReturnValue({
postMessage: () => undefined,
});
- const sendMessageSpy = spyOn(window.opener, 'postMessage');
+ const sendMessageSpy = vi.spyOn(window.opener, 'postMessage');
// act
popUpService.sendMessageToMainWindow('someUrl', {});
// assert
- expect(sendMessageSpy).toHaveBeenCalledOnceWith(
+ expect(sendMessageSpy).toHaveBeenCalledExactlyOnceWith(
'someUrl',
- jasmine.any(String)
+ expect.any(String)
);
- }));
+ });
});
describe('cleanUp', () => {
- it('calls removeEventListener on window with correct params', waitForAsync(() => {
+ it('calls removeEventListener on window with correct params', async () => {
// arrange
- const spy = spyOn(window, 'removeEventListener').and.callFake(
- () => undefined
- );
+ const spy = vi
+ .spyOn(window, 'removeEventListener')
+ .mockImplementation(() => undefined);
const listener: any = null;
// act
@@ -315,29 +313,29 @@ describe('PopUpService', () => {
// assert
expect(spy).toHaveBeenCalledTimes(1);
- expect(spy).toHaveBeenCalledOnceWith('message', listener, false);
- }));
+ expect(spy).toHaveBeenCalledExactlyOnceWith('message', listener, false);
+ });
- it('removes popup from sessionstorage, closes and nulls when popup is opened', waitForAsync(() => {
+ it('removes popup from sessionstorage, closes and nulls when popup is opened', async () => {
// arrange
const popupMock = {
anyThing: 'truthy',
sessionStorage: mockStorage,
close: (): void => undefined,
};
- const removeItemSpy = spyOn(storagePersistenceService, 'remove');
- const closeSpy = spyOn(popupMock, 'close');
+ const removeItemSpy = vi.spyOn(storagePersistenceService, 'remove');
+ const closeSpy = vi.spyOn(popupMock, 'close');
// act
(popUpService as any).popUp = popupMock;
(popUpService as any).cleanUp(null, { configId: 'configId1' });
// assert
- expect(removeItemSpy).toHaveBeenCalledOnceWith('popupauth', {
+ expect(removeItemSpy).toHaveBeenCalledExactlyOnceWith('popupauth', {
configId: 'configId1',
});
expect(closeSpy).toHaveBeenCalledTimes(1);
expect((popUpService as any).popUp).toBeNull();
- }));
+ });
});
});
diff --git a/src/login/response-type-validation/response-type-validation.service.spec.ts b/src/login/response-type-validation/response-type-validation.service.spec.ts
index 679841c..d3e0583 100644
--- a/src/login/response-type-validation/response-type-validation.service.spec.ts
+++ b/src/login/response-type-validation/response-type-validation.service.spec.ts
@@ -1,6 +1,7 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { FlowHelper } from '../../utils/flowHelper/flow-helper.service';
import { ResponseTypeValidationService } from './response-type-validation.service';
@@ -32,7 +33,9 @@ describe('ResponseTypeValidationService', () => {
describe('hasConfigValidResponseType', () => {
it('returns true if current configured flow is any implicit flow', () => {
- spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
+ vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
+ true
+ );
const result = responseTypeValidationService.hasConfigValidResponseType({
configId: 'configId1',
@@ -42,8 +45,10 @@ describe('ResponseTypeValidationService', () => {
});
it('returns true if current configured flow is code flow', () => {
- spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
+ vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
+ false
+ );
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
const result = responseTypeValidationService.hasConfigValidResponseType({
configId: 'configId1',
@@ -53,8 +58,10 @@ describe('ResponseTypeValidationService', () => {
});
it('returns false if current configured flow is neither code nor implicit flow', () => {
- spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
+ false
+ );
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
const result = responseTypeValidationService.hasConfigValidResponseType({
configId: 'configId1',
diff --git a/src/login/standard/standard-login.service.spec.ts b/src/login/standard/standard-login.service.spec.ts
index 4313ccc..f655eaf 100644
--- a/src/login/standard/standard-login.service.spec.ts
+++ b/src/login/standard/standard-login.service.spec.ts
@@ -1,9 +1,10 @@
-import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
+import { TestBed, fakeAsync, tick } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
+import { vi } from 'vitest';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
import { FlowsDataService } from '../../flows/flows-data.service';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { RedirectService } from '../../utils/redirect/redirect.service';
import { UrlService } from '../../utils/url/url.service';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
@@ -51,12 +52,12 @@ describe('StandardLoginService', () => {
});
describe('loginStandard', () => {
- it('does nothing if it has an invalid response type', waitForAsync(() => {
- spyOn(
+ it('does nothing if it has an invalid response type', async () => {
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(false);
- const loggerSpy = spyOn(loggerService, 'logError');
+ ).mockReturnValue(false);
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const result = standardLoginService.loginStandard({
configId: 'configId1',
@@ -64,95 +65,92 @@ describe('StandardLoginService', () => {
expect(result).toBeUndefined();
expect(loggerSpy).toHaveBeenCalled();
- }));
+ });
- it('calls flowsDataService.setCodeFlowInProgress() if everything fits', waitForAsync(() => {
+ it('calls flowsDataService.setCodeFlowInProgress() if everything fits', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- const flowsDataSpy = spyOn(flowsDataService, 'setCodeFlowInProgress');
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ const flowsDataSpy = vi.spyOn(flowsDataService, 'setCodeFlowInProgress');
const result = standardLoginService.loginStandard(config);
expect(result).toBeUndefined();
expect(flowsDataSpy).toHaveBeenCalled();
- }));
+ });
- it('calls urlService.getAuthorizeUrl() if everything fits', waitForAsync(() => {
+ it('calls urlService.getAuthorizeUrl() if everything fits', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
const result = standardLoginService.loginStandard(config);
expect(result).toBeUndefined();
- }));
+ });
- it('redirects to URL with no URL handler', fakeAsync(() => {
+ it('redirects to URL with no URL handler', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- const redirectSpy = spyOn(
- redirectService,
- 'redirectTo'
- ).and.callThrough();
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo')();
standardLoginService.loginStandard(config);
tick();
- expect(redirectSpy).toHaveBeenCalledOnceWith('someUrl');
- }));
+ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
+ });
- it('redirects to URL with URL handler when urlHandler is given', fakeAsync(() => {
+ it('redirects to URL with URL handler when urlHandler is given', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
- () => undefined
- );
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ const redirectSpy = vi
+ .spyOn(redirectService, 'redirectTo')
+ .mockImplementation(() => undefined);
const spy = jasmine.createSpy();
const urlHandler = (url: any): void => {
spy(url);
@@ -160,94 +158,96 @@ describe('StandardLoginService', () => {
standardLoginService.loginStandard(config, { urlHandler });
tick();
- expect(spy).toHaveBeenCalledOnceWith('someUrl');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl');
expect(redirectSpy).not.toHaveBeenCalled();
- }));
+ });
- it('calls resetSilentRenewRunning', fakeAsync(() => {
+ it('calls resetSilentRenewRunning', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
- const flowsDataSpy = spyOn(flowsDataService, 'resetSilentRenewRunning');
+ ).mockReturnValue(of({}));
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
+ const flowsDataSpy = vi.spyOn(
+ flowsDataService,
+ 'resetSilentRenewRunning'
+ );
standardLoginService.loginStandard(config, {});
tick();
expect(flowsDataSpy).toHaveBeenCalled();
- }));
+ });
- it('calls getAuthorizeUrl with custom params if they are given as parameter', fakeAsync(() => {
+ it('calls getAuthorizeUrl with custom params if they are given as parameter', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- const getAuthorizeUrlSpy = spyOn(
- urlService,
- 'getAuthorizeUrl'
- ).and.returnValue(of('someUrl'));
- const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
- () => undefined
- );
+ ).mockReturnValue(of({}));
+ const getAuthorizeUrlSpy = vi
+ .spyOn(urlService, 'getAuthorizeUrl')
+ .mockReturnValue(of('someUrl'));
+ const redirectSpy = vi
+ .spyOn(redirectService, 'redirectTo')
+ .mockImplementation(() => undefined);
standardLoginService.loginStandard(config, {
customParams: { to: 'add', as: 'well' },
});
tick();
- expect(redirectSpy).toHaveBeenCalledOnceWith('someUrl');
- expect(getAuthorizeUrlSpy).toHaveBeenCalledOnceWith(config, {
+ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
+ expect(getAuthorizeUrlSpy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { to: 'add', as: 'well' },
});
- }));
+ });
- it('does nothing, logs only if getAuthorizeUrl returns falsy', fakeAsync(() => {
+ it('does nothing, logs only if getAuthorizeUrl returns falsy', async () => {
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
- spyOn(
+ vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
- const loggerSpy = spyOn(loggerService, 'logError');
+ ).mockReturnValue(of({}));
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
- spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of(''));
- const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
- () => undefined
- );
+ vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of(''));
+ const redirectSpy = vi
+ .spyOn(redirectService, 'redirectTo')
+ .mockImplementation(() => undefined);
standardLoginService.loginStandard(config);
tick();
- expect(loggerSpy).toHaveBeenCalledOnceWith(
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
config,
'Could not create URL',
''
);
expect(redirectSpy).not.toHaveBeenCalled();
- }));
+ });
});
});
diff --git a/src/logoff-revoke/logoff-revocation.service.spec.ts b/src/logoff-revoke/logoff-revocation.service.spec.ts
index 94d6299..2601739 100644
--- a/src/logoff-revoke/logoff-revocation.service.spec.ts
+++ b/src/logoff-revoke/logoff-revocation.service.spec.ts
@@ -1,13 +1,14 @@
-import { HttpHeaders } from '@angular/common/http';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import type { HttpHeaders } from '@ngify/http';
import { Observable, of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { createRetriableStream } from '../../test/create-retriable-stream.helper';
+import { vi } from 'vitest';
import { DataService } from '../api/data.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { CheckSessionService } from '../iframe/check-session.service';
import { LoggerService } from '../logging/logger.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { createRetriableStream } from '../testing/create-retriable-stream.helper';
+import { mockProvider } from '../testing/mock';
import { RedirectService } from '../utils/redirect/redirect.service';
import { UrlService } from '../utils/url/url.service';
import { LogoffRevocationService } from './logoff-revocation.service';
@@ -55,70 +56,70 @@ describe('Logout and Revoke Service', () => {
it('uses token parameter if token as parameter is passed in the method', () => {
// Arrange
const paramToken = 'passedTokenAsParam';
- const revocationSpy = spyOn(
+ const revocationSpy = vi.spyOn(
urlService,
'createRevocationEndpointBodyAccessToken'
);
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
// Act
service.revokeAccessToken(config, paramToken);
// Assert
- expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
+ expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
});
it('uses token parameter from persistence if no param is provided', () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- const revocationSpy = spyOn(
+ const revocationSpy = vi.spyOn(
urlService,
'createRevocationEndpointBodyAccessToken'
);
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1' };
// Act
service.revokeAccessToken(config);
// Assert
- expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
+ expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
});
it('returns type observable', () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1' };
// Act
const result = service.revokeAccessToken(config);
// Assert
- expect(result).toEqual(jasmine.any(Observable));
+ expect(result).toEqual(expect.any(Observable));
});
- it('loggs and returns unmodified response if request is positive', waitForAsync(() => {
+ it('loggs and returns unmodified response if request is positive', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
- spyOn(dataService, 'post').and.returnValue(of({ data: 'anything' }));
+ vi.spyOn(dataService, 'post').mockReturnValue(of({ data: 'anything' }));
const config = { configId: 'configId1' };
// Act
@@ -127,20 +128,20 @@ describe('Logout and Revoke Service', () => {
expect(result).toEqual({ data: 'anything' });
expect(loggerSpy).toHaveBeenCalled();
});
- }));
+ });
- it('loggs error when request is negative', waitForAsync(() => {
+ it('loggs error when request is negative', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
throwError(() => new Error('Error'))
);
@@ -151,20 +152,20 @@ describe('Logout and Revoke Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('should retry once', waitForAsync(() => {
+ it('should retry once', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
of({ data: 'anything' })
@@ -179,20 +180,20 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
- it('should retry twice', waitForAsync(() => {
+ it('should retry twice', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -208,20 +209,20 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
- it('should fail after three tries', waitForAsync(() => {
+ it('should fail after three tries', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -236,76 +237,76 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
});
describe('revokeRefreshToken', () => {
it('uses refresh token parameter if token as parameter is passed in the method', () => {
// Arrange
const paramToken = 'passedTokenAsParam';
- const revocationSpy = spyOn(
+ const revocationSpy = vi.spyOn(
urlService,
'createRevocationEndpointBodyRefreshToken'
);
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1' };
// Act
service.revokeRefreshToken(config, paramToken);
// Assert
- expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
+ expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
});
it('uses refresh token parameter from persistence if no param is provided', () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
const config = { configId: 'configId1' };
- const revocationSpy = spyOn(
+ const revocationSpy = vi.spyOn(
urlService,
'createRevocationEndpointBodyRefreshToken'
);
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
// Act
service.revokeRefreshToken(config);
// Assert
- expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
+ expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
});
it('returns type observable', () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- spyOn(dataService, 'post').and.returnValue(of(null));
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1' };
// Act
const result = service.revokeRefreshToken(config);
// Assert
- expect(result).toEqual(jasmine.any(Observable));
+ expect(result).toEqual(expect.any(Observable));
});
- it('loggs and returns unmodified response if request is positive', waitForAsync(() => {
+ it('loggs and returns unmodified response if request is positive', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
- spyOn(dataService, 'post').and.returnValue(of({ data: 'anything' }));
+ vi.spyOn(dataService, 'post').mockReturnValue(of({ data: 'anything' }));
const config = { configId: 'configId1' };
// Act
@@ -314,20 +315,20 @@ describe('Logout and Revoke Service', () => {
expect(result).toEqual({ data: 'anything' });
expect(loggerSpy).toHaveBeenCalled();
});
- }));
+ });
- it('loggs error when request is negative', waitForAsync(() => {
+ it('loggs error when request is negative', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
throwError(() => new Error('Error'))
);
@@ -338,20 +339,20 @@ describe('Logout and Revoke Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('should retry once', waitForAsync(() => {
+ it('should retry once', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
of({ data: 'anything' })
@@ -366,20 +367,20 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
- it('should retry twice', waitForAsync(() => {
+ it('should retry twice', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -395,20 +396,20 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
- it('should fail after three tries', waitForAsync(() => {
+ it('should fail after three tries', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
- const loggerSpy = spyOn(loggerService, 'logError');
+ vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = { configId: 'configId1' };
- spyOn(dataService, 'post').and.returnValue(
+ vi.spyOn(dataService, 'post').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -423,15 +424,15 @@ describe('Logout and Revoke Service', () => {
expect(loggerSpy).toHaveBeenCalled();
},
});
- }));
+ });
});
describe('logoff', () => {
- it('logs and returns if `endSessionUrl` is false', waitForAsync(() => {
+ it('logs and returns if `endSessionUrl` is false', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('');
- const serverStateChangedSpy = spyOn(
+ const serverStateChangedSpy = vi.spyOn(
checkSessionService,
'serverStateChanged'
);
@@ -444,14 +445,14 @@ describe('Logout and Revoke Service', () => {
result$.subscribe(() => {
expect(serverStateChangedSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('logs and returns if `serverStateChanged` is true', waitForAsync(() => {
+ it('logs and returns if `serverStateChanged` is true', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
- const redirectSpy = spyOn(redirectService, 'redirectTo');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(true);
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(true);
const config = { configId: 'configId1' };
// Act
@@ -461,22 +462,24 @@ describe('Logout and Revoke Service', () => {
result$.subscribe(() => {
expect(redirectSpy).not.toHaveBeenCalled();
});
- }));
+ });
- it('calls urlHandler if urlhandler is passed', waitForAsync(() => {
+ it('calls urlHandler if urlhandler is passed', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
const spy = jasmine.createSpy();
const urlHandler = (url: string): void => {
spy(url);
};
- const redirectSpy = spyOn(redirectService, 'redirectTo');
- const resetAuthorizationDataSpy = spyOn(
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
+ false
+ );
const config = { configId: 'configId1' };
// Act
@@ -485,18 +488,20 @@ describe('Logout and Revoke Service', () => {
// Assert
result$.subscribe(() => {
expect(redirectSpy).not.toHaveBeenCalled();
- expect(spy).toHaveBeenCalledOnceWith('someValue');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('someValue');
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
});
- }));
+ });
- it('calls redirect service if no logoutOptions are passed', waitForAsync(() => {
+ it('calls redirect service if no logoutOptions are passed', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
- const redirectSpy = spyOn(redirectService, 'redirectTo');
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
+ false
+ );
const config = { configId: 'configId1' };
// Act
@@ -504,17 +509,19 @@ describe('Logout and Revoke Service', () => {
// Assert
result$.subscribe(() => {
- expect(redirectSpy).toHaveBeenCalledOnceWith('someValue');
+ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
});
- }));
+ });
- it('calls redirect service if logoutOptions are passed and method is GET', waitForAsync(() => {
+ it('calls redirect service if logoutOptions are passed and method is GET', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
- const redirectSpy = spyOn(redirectService, 'redirectTo');
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
+ false
+ );
const config = { configId: 'configId1' };
// Act
@@ -522,28 +529,30 @@ describe('Logout and Revoke Service', () => {
// Assert
result$.subscribe(() => {
- expect(redirectSpy).toHaveBeenCalledOnceWith('someValue');
+ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
});
- }));
+ });
- it('calls dataservice post if logoutOptions are passed and method is POST', waitForAsync(() => {
+ it('calls dataservice post if logoutOptions are passed and method is POST', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
- const redirectSpy = spyOn(redirectService, 'redirectTo');
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
+ false
+ );
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'id-token'
);
- spyOn(urlService, 'getPostLogoutRedirectUrl').and.returnValue(
+ vi.spyOn(urlService, 'getPostLogoutRedirectUrl').mockReturnValue(
'post-logout-redirect-url'
);
- spyOn(urlService, 'getEndSessionEndpoint').and.returnValue({
+ vi.spyOn(urlService, 'getEndSessionEndpoint').mockReturnValue({
url: 'some-url',
existingParams: '',
});
- const postSpy = spyOn(dataService, 'post').and.returnValue(of(null));
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1', clientId: 'clientId' };
// Act
@@ -554,7 +563,7 @@ describe('Logout and Revoke Service', () => {
// Assert
result$.subscribe(() => {
expect(redirectSpy).not.toHaveBeenCalled();
- expect(postSpy).toHaveBeenCalledOnceWith(
+ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'some-url',
{
id_token_hint: 'id-token',
@@ -562,36 +571,38 @@ describe('Logout and Revoke Service', () => {
post_logout_redirect_uri: 'post-logout-redirect-url',
},
config,
- jasmine.anything()
+ expect.anything()
);
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
- expect(httpHeaders.has('Content-Type')).toBeTrue();
+ expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded'
);
});
- }));
+ });
- it('calls dataservice post if logoutOptions with customParams are passed and method is POST', waitForAsync(() => {
+ it('calls dataservice post if logoutOptions with customParams are passed and method is POST', async () => {
// Arrange
- spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
+ vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
- const redirectSpy = spyOn(redirectService, 'redirectTo');
+ const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
- spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
+ false
+ );
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'id-token'
);
- spyOn(urlService, 'getPostLogoutRedirectUrl').and.returnValue(
+ vi.spyOn(urlService, 'getPostLogoutRedirectUrl').mockReturnValue(
'post-logout-redirect-url'
);
- spyOn(urlService, 'getEndSessionEndpoint').and.returnValue({
+ vi.spyOn(urlService, 'getEndSessionEndpoint').mockReturnValue({
url: 'some-url',
existingParams: '',
});
- const postSpy = spyOn(dataService, 'post').and.returnValue(of(null));
+ const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of(null));
const config = { configId: 'configId1', clientId: 'clientId' };
// Act
@@ -607,7 +618,7 @@ describe('Logout and Revoke Service', () => {
// Assert
result$.subscribe(() => {
expect(redirectSpy).not.toHaveBeenCalled();
- expect(postSpy).toHaveBeenCalledOnceWith(
+ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'some-url',
{
id_token_hint: 'id-token',
@@ -618,23 +629,23 @@ describe('Logout and Revoke Service', () => {
ui_locales: 'de fr en',
},
config,
- jasmine.anything()
+ expect.anything()
);
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
- expect(httpHeaders.has('Content-Type')).toBeTrue();
+ expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded'
);
});
- }));
+ });
});
describe('logoffLocal', () => {
it('calls flowsService.resetAuthorizationData', () => {
// Arrange
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
@@ -649,25 +660,25 @@ describe('Logout and Revoke Service', () => {
});
describe('logoffAndRevokeTokens', () => {
- it('calls revokeRefreshToken and revokeAccessToken when storage holds a refreshtoken', waitForAsync(() => {
+ it('calls revokeRefreshToken and revokeAccessToken when storage holds a refreshtoken', async () => {
// Arrange
const paramToken = 'damien';
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ revocationEndpoint: 'revocationEndpoint' })
+ );
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- const revokeRefreshTokenSpy = spyOn(
- service,
- 'revokeRefreshToken'
- ).and.returnValue(of({ any: 'thing' }));
- const revokeAccessTokenSpy = spyOn(
- service,
- 'revokeAccessToken'
- ).and.returnValue(of({ any: 'thing' }));
+ const revokeRefreshTokenSpy = vi
+ .spyOn(service, 'revokeRefreshToken')
+ .mockReturnValue(of({ any: 'thing' }));
+ const revokeAccessTokenSpy = vi
+ .spyOn(service, 'revokeAccessToken')
+ .mockReturnValue(of({ any: 'thing' }));
// Act
service.logoffAndRevokeTokens(config, [config]).subscribe(() => {
@@ -675,25 +686,27 @@ describe('Logout and Revoke Service', () => {
expect(revokeRefreshTokenSpy).toHaveBeenCalled();
expect(revokeAccessTokenSpy).toHaveBeenCalled();
});
- }));
+ });
- it('logs error when revokeaccesstoken throws an error', waitForAsync(() => {
+ it('logs error when revokeaccesstoken throws an error', async () => {
// Arrange
const paramToken = 'damien';
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ revocationEndpoint: 'revocationEndpoint' })
+ );
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(service, 'revokeRefreshToken').and.returnValue(
+ vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
of({ any: 'thing' })
);
- const loggerSpy = spyOn(loggerService, 'logError');
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
- spyOn(service, 'revokeAccessToken').and.returnValue(
+ vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
throwError(() => new Error('Error'))
);
@@ -704,20 +717,22 @@ describe('Logout and Revoke Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
- it('calls logoff in case of success', waitForAsync(() => {
+ it('calls logoff in case of success', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(service, 'revokeRefreshToken').and.returnValue(
+ vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
of({ any: 'thing' })
);
- spyOn(service, 'revokeAccessToken').and.returnValue(of({ any: 'thing' }));
- const logoffSpy = spyOn(service, 'logoff').and.returnValue(of(null));
+ vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
+ of({ any: 'thing' })
+ );
+ const logoffSpy = vi.spyOn(service, 'logoff').mockReturnValue(of(null));
const config = { configId: 'configId1' };
// Act
@@ -725,20 +740,22 @@ describe('Logout and Revoke Service', () => {
// Assert
expect(logoffSpy).toHaveBeenCalled();
});
- }));
+ });
- it('calls logoff with urlhandler in case of success', waitForAsync(() => {
+ it('calls logoff with urlhandler in case of success', async () => {
// Arrange
const paramToken = 'damien';
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
paramToken
);
- spyOn(service, 'revokeRefreshToken').and.returnValue(
+ vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
of({ any: 'thing' })
);
- spyOn(service, 'revokeAccessToken').and.returnValue(of({ any: 'thing' }));
- const logoffSpy = spyOn(service, 'logoff').and.returnValue(of(null));
+ vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
+ of({ any: 'thing' })
+ );
+ const logoffSpy = vi.spyOn(service, 'logoff').mockReturnValue(of(null));
const urlHandler = (_url: string): void => undefined;
const config = { configId: 'configId1' };
@@ -747,26 +764,29 @@ describe('Logout and Revoke Service', () => {
.logoffAndRevokeTokens(config, [config], { urlHandler })
.subscribe(() => {
// Assert
- expect(logoffSpy).toHaveBeenCalledOnceWith(config, [config], {
+ expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
urlHandler,
});
});
- }));
+ });
- it('calls revokeAccessToken when storage does not hold a refreshtoken', waitForAsync(() => {
+ it('calls revokeAccessToken when storage does not hold a refreshtoken', async () => {
// Arrange
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ revocationEndpoint: 'revocationEndpoint' })
+ );
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue('');
- const revokeRefreshTokenSpy = spyOn(service, 'revokeRefreshToken');
- const revokeAccessTokenSpy = spyOn(
- service,
- 'revokeAccessToken'
- ).and.returnValue(of({ any: 'thing' }));
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
+ ''
+ );
+ const revokeRefreshTokenSpy = vi.spyOn(service, 'revokeRefreshToken');
+ const revokeAccessTokenSpy = vi
+ .spyOn(service, 'revokeAccessToken')
+ .mockReturnValue(of({ any: 'thing' }));
// Act
service.logoffAndRevokeTokens(config, [config]).subscribe(() => {
@@ -774,19 +794,23 @@ describe('Logout and Revoke Service', () => {
expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();
expect(revokeAccessTokenSpy).toHaveBeenCalled();
});
- }));
+ });
- it('logs error when revokeaccesstoken throws an error', waitForAsync(() => {
+ it('logs error when revokeaccesstoken throws an error', async () => {
// Arrange
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
- spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue('');
- const loggerSpy = spyOn(loggerService, 'logError');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ revocationEndpoint: 'revocationEndpoint' })
+ );
+ vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
+ ''
+ );
+ const loggerSpy = vi.spyOn(loggerService, 'logError');
- spyOn(service, 'revokeAccessToken').and.returnValue(
+ vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
throwError(() => new Error('Error'))
);
@@ -797,18 +821,18 @@ describe('Logout and Revoke Service', () => {
expect(err).toBeTruthy();
},
});
- }));
+ });
});
describe('logoffLocalMultiple', () => {
it('calls logoffLocal for every config which is present', () => {
// Arrange
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
- const resetAuthorizationDataSpy = spyOn(
+ const resetAuthorizationDataSpy = vi.spyOn(
resetAuthDataService,
'resetAuthorizationData'
);
- const checkSessionServiceSpy = spyOn(checkSessionService, 'stop');
+ const checkSessionServiceSpy = vi.spyOn(checkSessionService, 'stop');
// Act
service.logoffLocalMultiple(allConfigs);
@@ -816,8 +840,8 @@ describe('Logout and Revoke Service', () => {
// Assert
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(2);
expect(checkSessionServiceSpy).toHaveBeenCalledTimes(2);
- expect(resetAuthorizationDataSpy.calls.allArgs()).toEqual([
- [allConfigs[0], allConfigs],
+ expect(resetAuthorizationDataSpy).toBeCalledWith([
+ [allConfigs[0]!, allConfigs],
[allConfigs[1], allConfigs],
]);
});
diff --git a/src/logoff-revoke/logoff-revocation.service.ts b/src/logoff-revoke/logoff-revocation.service.ts
index b3187d6..8988c59 100644
--- a/src/logoff-revoke/logoff-revocation.service.ts
+++ b/src/logoff-revoke/logoff-revocation.service.ts
@@ -1,10 +1,10 @@
import { HttpHeaders } from '@ngify/http';
-import { inject, Injectable } from 'injection-js';
-import { Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { type Observable, of, throwError } from 'rxjs';
import { catchError, concatMap, retry, switchMap } from 'rxjs/operators';
import { DataService } from '../api/data.service';
-import { LogoutAuthOptions } from '../auth-options';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { LogoutAuthOptions } from '../auth-options';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { CheckSessionService } from '../iframe/check-session.service';
import { LoggerService } from '../logging/logger.service';
diff --git a/src/oidc.security.service.spec.ts b/src/oidc.security.service.spec.ts
index e9d124d..bffcd4b 100644
--- a/src/oidc.security.service.spec.ts
+++ b/src/oidc.security.service.spec.ts
@@ -1,6 +1,6 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { Observable, of } from 'rxjs';
-import { mockProvider } from '../test/auto-mock';
+import { TestBed } from '@/testing';
+import { Observable, lastValueFrom, of } from 'rxjs';
+import { vi } from 'vitest';
import { AuthStateService } from './auth-state/auth-state.service';
import { CheckAuthService } from './auth-state/check-auth.service';
import { CallbackService } from './callback/callback.service';
@@ -9,10 +9,11 @@ import { AuthWellKnownService } from './config/auth-well-known/auth-well-known.s
import { ConfigurationService } from './config/config.service';
import { FlowsDataService } from './flows/flows-data.service';
import { CheckSessionService } from './iframe/check-session.service';
-import { LoginResponse } from './login/login-response';
+import type { LoginResponse } from './login/login-response';
import { LoginService } from './login/login.service';
import { LogoffRevocationService } from './logoff-revoke/logoff-revocation.service';
import { OidcSecurityService } from './oidc.security.service';
+import { mockProvider } from './testing/mock';
import { UserService } from './user-data/user.service';
import { TokenHelperService } from './utils/tokenHelper/token-helper.service';
import { UrlService } from './utils/url/url.service';
@@ -55,9 +56,6 @@ describe('OidcSecurityService', () => {
mockProvider(AuthWellKnownService),
],
});
- });
-
- beforeEach(() => {
authStateService = TestBed.inject(AuthStateService);
tokenHelperService = TestBed.inject(TokenHelperService);
configurationService = TestBed.inject(ConfigurationService);
@@ -73,15 +71,14 @@ describe('OidcSecurityService', () => {
callbackService = TestBed.inject(CallbackService);
// this is required because these methods will be invoked by the signal properties when the service is created
- authenticatedSpy = spyOnProperty(
- authStateService,
- 'authenticated$'
- ).and.returnValue(
- of({ isAuthenticated: false, allConfigsAuthenticated: [] })
- );
- userDataSpy = spyOnProperty(userService, 'userData$').and.returnValue(
- of({ userData: null, allUserData: [] })
- );
+ authenticatedSpy = vi
+ .spyOnProperty(authStateService, 'authenticated$')
+ .mockReturnValue(
+ of({ isAuthenticated: false, allConfigsAuthenticated: [] })
+ );
+ userDataSpy = vi
+ .spyOnProperty(userService, 'userData$')
+ .mockReturnValue(of({ userData: null, allUserData: [] }));
oidcSecurityService = TestBed.inject(OidcSecurityService);
});
@@ -90,94 +87,93 @@ describe('OidcSecurityService', () => {
});
describe('userData$', () => {
- it('calls userService.userData$', waitForAsync(() => {
+ it('calls userService.userData$', async () => {
oidcSecurityService.userData$.subscribe(() => {
// 1x from this subscribe
// 1x by the signal property
expect(userDataSpy).toHaveBeenCalledTimes(2);
});
- }));
+ });
});
describe('userData', () => {
- it('calls userService.userData$', waitForAsync(() => {
- const _userdata = oidcSecurityService.userData();
+ it('calls userService.userData$', async () => {
+ const _userdata = await lastValueFrom(oidcSecurityService.userData());
expect(userDataSpy).toHaveBeenCalledTimes(1);
- }));
+ });
});
describe('isAuthenticated$', () => {
- it('calls authStateService.isAuthenticated$', waitForAsync(() => {
+ it('calls authStateService.isAuthenticated$', async () => {
oidcSecurityService.isAuthenticated$.subscribe(() => {
// 1x from this subscribe
// 1x by the signal property
expect(authenticatedSpy).toHaveBeenCalledTimes(2);
});
- }));
+ });
});
describe('authenticated', () => {
- it('calls authStateService.isAuthenticated$', waitForAsync(() => {
- const _authenticated = oidcSecurityService.authenticated();
+ it('calls authStateService.isAuthenticated$', async () => {
+ const _authenticated = await lastValueFrom(
+ oidcSecurityService.authenticated()
+ );
expect(authenticatedSpy).toHaveBeenCalledTimes(1);
- }));
+ });
});
describe('checkSessionChanged$', () => {
- it('calls checkSessionService.checkSessionChanged$', waitForAsync(() => {
- const spy = spyOnProperty(
- checkSessionService,
- 'checkSessionChanged$'
- ).and.returnValue(of(true));
+ it('calls checkSessionService.checkSessionChanged$', async () => {
+ const spy = vi
+ .spyOnProperty(checkSessionService, 'checkSessionChanged$')
+ .mockReturnValue(of(true));
oidcSecurityService.checkSessionChanged$.subscribe(() => {
expect(spy).toHaveBeenCalledTimes(1);
});
- }));
+ });
});
describe('stsCallback$', () => {
- it('calls callbackService.stsCallback$', waitForAsync(() => {
- const spy = spyOnProperty(
- callbackService,
- 'stsCallback$'
- ).and.returnValue(of());
+ it('calls callbackService.stsCallback$', async () => {
+ const spy = vi
+ .spyOnProperty(callbackService, 'stsCallback$')
+ .mockReturnValue(of());
oidcSecurityService.stsCallback$.subscribe(() => {
expect(spy).toHaveBeenCalledTimes(1);
});
- }));
+ });
});
describe('preloadAuthWellKnownDocument', () => {
- it('calls authWellKnownService.queryAndStoreAuthWellKnownEndPoints with config', waitForAsync(() => {
+ it('calls authWellKnownService.queryAndStoreAuthWellKnownEndPoints with config', async () => {
const config = { configId: 'configid1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- authWellKnownService,
- 'queryAndStoreAuthWellKnownEndPoints'
- ).and.returnValue(of({}));
+ const spy = vi
+ .spyOn(authWellKnownService, 'queryAndStoreAuthWellKnownEndPoints')
+ .mockReturnValue(of({}));
oidcSecurityService.preloadAuthWellKnownDocument().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('getConfigurations', () => {
it('is not of type observable', () => {
expect(oidcSecurityService.getConfigurations).not.toEqual(
- jasmine.any(Observable)
+ expect.any(Observable)
);
});
it('calls configurationProvider.getAllConfigurations', () => {
- const spy = spyOn(configurationService, 'getAllConfigurations');
+ const spy = vi.spyOn(configurationService, 'getAllConfigurations');
oidcSecurityService.getConfigurations();
@@ -188,607 +184,635 @@ describe('OidcSecurityService', () => {
describe('getConfiguration', () => {
it('is not of type observable', () => {
expect(oidcSecurityService.getConfiguration).not.toEqual(
- jasmine.any(Observable)
+ expect.any(Observable)
);
});
it('calls configurationProvider.getOpenIDConfiguration with passed configId when configId is passed', () => {
- const spy = spyOn(configurationService, 'getOpenIDConfiguration');
+ const spy = vi.spyOn(configurationService, 'getOpenIDConfiguration');
oidcSecurityService.getConfiguration('configId');
- expect(spy).toHaveBeenCalledOnceWith('configId');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('configId');
});
});
describe('getUserData', () => {
- it('calls configurationProvider.getOpenIDConfiguration with config', waitForAsync(() => {
+ it('calls configurationProvider.getOpenIDConfiguration with config', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(userService, 'getUserDataFromStore').and.returnValue({
- some: 'thing',
- });
+ const spy = vi
+ .spyOn(userService, 'getUserDataFromStore')
+ .mockReturnValue({
+ some: 'thing',
+ });
oidcSecurityService.getUserData('configId').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
- it('returns userdata', waitForAsync(() => {
+ it('returns userdata', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- spyOn(userService, 'getUserDataFromStore').and.returnValue({
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue({
some: 'thing',
});
oidcSecurityService.getUserData('configId').subscribe((result) => {
expect(result).toEqual({ some: 'thing' });
});
- }));
+ });
});
describe('checkAuth', () => {
- it('calls checkAuthService.checkAuth() without url if none is passed', waitForAsync(() => {
+ it('calls checkAuthService.checkAuth() without url if none is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
- of({} as LoginResponse)
- );
+ const spy = vi
+ .spyOn(checkAuthService, 'checkAuth')
+ .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuth().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ undefined
+ );
});
- }));
+ });
- it('calls checkAuthService.checkAuth() with url if one is passed', waitForAsync(() => {
+ it('calls checkAuthService.checkAuth() with url if one is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
- of({} as LoginResponse)
- );
+ const spy = vi
+ .spyOn(checkAuthService, 'checkAuth')
+ .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuth('some-url').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-url');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ 'some-url'
+ );
});
- }));
+ });
});
describe('checkAuthMultiple', () => {
- it('calls checkAuthService.checkAuth() without url if none is passed', waitForAsync(() => {
+ it('calls checkAuthService.checkAuth() without url if none is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(checkAuthService, 'checkAuthMultiple').and.returnValue(
- of([{}] as LoginResponse[])
- );
+ const spy = vi
+ .spyOn(checkAuthService, 'checkAuthMultiple')
+ .mockReturnValue(of([{}] as LoginResponse[]));
oidcSecurityService.checkAuthMultiple().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith([config], undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith([config], undefined);
});
- }));
+ });
- it('calls checkAuthService.checkAuthMultiple() with url if one is passed', waitForAsync(() => {
+ it('calls checkAuthService.checkAuthMultiple() with url if one is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(checkAuthService, 'checkAuthMultiple').and.returnValue(
- of([{}] as LoginResponse[])
- );
+ const spy = vi
+ .spyOn(checkAuthService, 'checkAuthMultiple')
+ .mockReturnValue(of([{}] as LoginResponse[]));
oidcSecurityService.checkAuthMultiple('some-url').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith([config], 'some-url');
+ expect(spy).toHaveBeenCalledExactlyOnceWith([config], 'some-url');
});
- }));
+ });
});
describe('isAuthenticated()', () => {
- it('calls authStateService.isAuthenticated with passed configId when configId is passed', waitForAsync(() => {
+ it('calls authStateService.isAuthenticated with passed configId when configId is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(authStateService, 'isAuthenticated').and.returnValue(
- true
- );
+ const spy = vi
+ .spyOn(authStateService, 'isAuthenticated')
+ .mockReturnValue(true);
oidcSecurityService.isAuthenticated().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('checkAuthIncludingServer', () => {
- it('calls checkAuthService.checkAuthIncludingServer()', waitForAsync(() => {
+ it('calls checkAuthService.checkAuthIncludingServer()', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(
- checkAuthService,
- 'checkAuthIncludingServer'
- ).and.returnValue(of({} as LoginResponse));
+ const spy = vi
+ .spyOn(checkAuthService, 'checkAuthIncludingServer')
+ .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuthIncludingServer().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config]);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]);
});
- }));
+ });
});
describe('getAccessToken', () => {
- it('calls authStateService.getAccessToken()', waitForAsync(() => {
+ it('calls authStateService.getAccessToken()', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(authStateService, 'getAccessToken').and.returnValue('');
+ const spy = vi
+ .spyOn(authStateService, 'getAccessToken')
+ .mockReturnValue('');
oidcSecurityService.getAccessToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('getIdToken', () => {
- it('calls authStateService.getIdToken()', waitForAsync(() => {
+ it('calls authStateService.getIdToken()', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(authStateService, 'getIdToken').and.returnValue('');
+ const spy = vi.spyOn(authStateService, 'getIdToken').mockReturnValue('');
oidcSecurityService.getIdToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('getRefreshToken', () => {
- it('calls authStateService.getRefreshToken()', waitForAsync(() => {
+ it('calls authStateService.getRefreshToken()', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(authStateService, 'getRefreshToken').and.returnValue(
- ''
- );
+ const spy = vi
+ .spyOn(authStateService, 'getRefreshToken')
+ .mockReturnValue('');
oidcSecurityService.getRefreshToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('getAuthenticationResult', () => {
- it('calls authStateService.getAuthenticationResult()', waitForAsync(() => {
+ it('calls authStateService.getAuthenticationResult()', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- authStateService,
- 'getAuthenticationResult'
- ).and.returnValue(null);
+ const spy = vi
+ .spyOn(authStateService, 'getAuthenticationResult')
+ .mockReturnValue(null);
oidcSecurityService.getAuthenticationResult().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('getPayloadFromIdToken', () => {
- it('calls `authStateService.getIdToken` method, encode = false', waitForAsync(() => {
+ it('calls `authStateService.getIdToken` method, encode = false', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- spyOn(authStateService, 'getIdToken').and.returnValue('some-token');
- const spy = spyOn(
- tokenHelperService,
- 'getPayloadFromToken'
- ).and.returnValue(null);
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('some-token');
+ const spy = vi
+ .spyOn(tokenHelperService, 'getPayloadFromToken')
+ .mockReturnValue(null);
oidcSecurityService.getPayloadFromIdToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-token', false, config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'some-token',
+ false,
+ config
+ );
});
- }));
+ });
- it('calls `authStateService.getIdToken` method, encode = true', waitForAsync(() => {
+ it('calls `authStateService.getIdToken` method, encode = true', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- spyOn(authStateService, 'getIdToken').and.returnValue('some-token');
- const spy = spyOn(
- tokenHelperService,
- 'getPayloadFromToken'
- ).and.returnValue(null);
+ vi.spyOn(authStateService, 'getIdToken').mockReturnValue('some-token');
+ const spy = vi
+ .spyOn(tokenHelperService, 'getPayloadFromToken')
+ .mockReturnValue(null);
oidcSecurityService.getPayloadFromIdToken(true).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-token', true, config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('some-token', true, config);
});
- }));
+ });
});
describe('getPayloadFromAccessToken', () => {
- it('calls `authStateService.getAccessToken` method, encode = false', waitForAsync(() => {
+ it('calls `authStateService.getAccessToken` method, encode = false', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- spyOn(authStateService, 'getAccessToken').and.returnValue(
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
'some-access-token'
);
- const spy = spyOn(
- tokenHelperService,
- 'getPayloadFromToken'
- ).and.returnValue(null);
+ const spy = vi
+ .spyOn(tokenHelperService, 'getPayloadFromToken')
+ .mockReturnValue(null);
oidcSecurityService.getPayloadFromAccessToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'some-access-token',
false,
config
);
});
- }));
+ });
- it('calls `authStateService.getIdToken` method, encode = true', waitForAsync(() => {
+ it('calls `authStateService.getIdToken` method, encode = true', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- spyOn(authStateService, 'getAccessToken').and.returnValue(
+ vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
'some-access-token'
);
- const spy = spyOn(
- tokenHelperService,
- 'getPayloadFromToken'
- ).and.returnValue(null);
+ const spy = vi
+ .spyOn(tokenHelperService, 'getPayloadFromToken')
+ .mockReturnValue(null);
oidcSecurityService.getPayloadFromAccessToken(true).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('some-access-token', true, config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'some-access-token',
+ true,
+ config
+ );
});
- }));
+ });
});
describe('setState', () => {
- it('calls flowsDataService.setAuthStateControl with param', waitForAsync(() => {
+ it('calls flowsDataService.setAuthStateControl with param', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(flowsDataService, 'setAuthStateControl');
+ const spy = vi.spyOn(flowsDataService, 'setAuthStateControl');
oidcSecurityService.setState('anyString').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith('anyString', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('anyString', config);
});
- }));
+ });
});
describe('getState', () => {
- it('calls flowsDataService.getAuthStateControl', waitForAsync(() => {
+ it('calls flowsDataService.getAuthStateControl', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(flowsDataService, 'getAuthStateControl');
+ const spy = vi.spyOn(flowsDataService, 'getAuthStateControl');
oidcSecurityService.getState().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
- }));
+ });
});
describe('authorize', () => {
- it('calls login service login', waitForAsync(() => {
+ it('calls login service login', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(loginService, 'login');
+ const spy = vi.spyOn(loginService, 'login');
- oidcSecurityService.authorize();
+ await lastValueFrom(oidcSecurityService.authorize());
- expect(spy).toHaveBeenCalledOnceWith(config, undefined);
- }));
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
+ });
- it('calls login service login with authoptions', waitForAsync(() => {
+ it('calls login service login with authoptions', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(loginService, 'login');
+ const spy = vi.spyOn(loginService, 'login');
- oidcSecurityService.authorize('configId', {
+ await lastValueFrom(
+ oidcSecurityService.authorize('configId', {
+ customParams: { some: 'param' },
+ })
+ );
+
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { some: 'param' },
});
-
- expect(spy).toHaveBeenCalledOnceWith(config, {
- customParams: { some: 'param' },
- });
- }));
+ });
});
describe('authorizeWithPopUp', () => {
- it('calls login service loginWithPopUp', waitForAsync(() => {
+ it('calls login service loginWithPopUp', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(loginService, 'loginWithPopUp').and.callFake(() =>
- of({} as LoginResponse)
- );
+ const spy = vi
+ .spyOn(loginService, 'loginWithPopUp')
+ .mockImplementation(() => of({} as LoginResponse));
oidcSecurityService.authorizeWithPopUp().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
config,
[config],
undefined,
undefined
);
});
- }));
+ });
});
describe('forceRefreshSession', () => {
- it('calls refreshSessionService userForceRefreshSession with configId from config when none is passed', waitForAsync(() => {
+ it('calls refreshSessionService userForceRefreshSession with configId from config when none is passed', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(
- refreshSessionService,
- 'userForceRefreshSession'
- ).and.returnValue(of({} as LoginResponse));
+ const spy = vi
+ .spyOn(refreshSessionService, 'userForceRefreshSession')
+ .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.forceRefreshSession().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ undefined
+ );
});
- }));
+ });
});
describe('logoffAndRevokeTokens', () => {
- it('calls logoffRevocationService.logoffAndRevokeTokens', waitForAsync(() => {
+ it('calls logoffRevocationService.logoffAndRevokeTokens', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(
- logoffRevocationService,
- 'logoffAndRevokeTokens'
- ).and.returnValue(of(null));
+ const spy = vi
+ .spyOn(logoffRevocationService, 'logoffAndRevokeTokens')
+ .mockReturnValue(of(null));
oidcSecurityService.logoffAndRevokeTokens().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ undefined
+ );
});
- }));
+ });
});
describe('logoff', () => {
- it('calls logoffRevocationService.logoff', waitForAsync(() => {
+ it('calls logoffRevocationService.logoff', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(logoffRevocationService, 'logoff').and.returnValue(
- of(null)
- );
+ const spy = vi
+ .spyOn(logoffRevocationService, 'logoff')
+ .mockReturnValue(of(null));
oidcSecurityService.logoff().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, [config], undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ config,
+ [config],
+ undefined
+ );
});
- }));
+ });
});
describe('logoffLocal', () => {
- it('calls logoffRevocationService.logoffLocal', waitForAsync(() => {
+ it('calls logoffRevocationService.logoffLocal', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(logoffRevocationService, 'logoffLocal');
+ const spy = vi.spyOn(logoffRevocationService, 'logoffLocal');
- oidcSecurityService.logoffLocal();
- expect(spy).toHaveBeenCalledOnceWith(config, [config]);
- }));
+ await lastValueFrom(oidcSecurityService.logoffLocal());
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]);
+ });
});
describe('logoffLocalMultiple', () => {
- it('calls logoffRevocationService.logoffLocalMultiple', waitForAsync(() => {
+ it('calls logoffRevocationService.logoffLocalMultiple', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfigurations').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfigurations').mockReturnValue(
of({ allConfigs: [config], currentConfig: config })
);
- const spy = spyOn(logoffRevocationService, 'logoffLocalMultiple');
+ const spy = vi.spyOn(logoffRevocationService, 'logoffLocalMultiple');
- oidcSecurityService.logoffLocalMultiple();
- expect(spy).toHaveBeenCalledOnceWith([config]);
- }));
+ await lastValueFrom(oidcSecurityService.logoffLocalMultiple());
+ expect(spy).toHaveBeenCalledExactlyOnceWith([config]);
+ });
});
describe('revokeAccessToken', () => {
- it('calls logoffRevocationService.revokeAccessToken', waitForAsync(() => {
+ it('calls logoffRevocationService.revokeAccessToken', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- logoffRevocationService,
- 'revokeAccessToken'
- ).and.returnValue(of(null));
+ const spy = vi
+ .spyOn(logoffRevocationService, 'revokeAccessToken')
+ .mockReturnValue(of(null));
oidcSecurityService.revokeAccessToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
- }));
+ });
- it('calls logoffRevocationService.revokeAccessToken with accesstoken', waitForAsync(() => {
+ it('calls logoffRevocationService.revokeAccessToken with accesstoken', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- logoffRevocationService,
- 'revokeAccessToken'
- ).and.returnValue(of(null));
+ const spy = vi
+ .spyOn(logoffRevocationService, 'revokeAccessToken')
+ .mockReturnValue(of(null));
oidcSecurityService.revokeAccessToken('access_token').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, 'access_token');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'access_token');
});
- }));
+ });
});
describe('revokeRefreshToken', () => {
- it('calls logoffRevocationService.revokeRefreshToken', waitForAsync(() => {
+ it('calls logoffRevocationService.revokeRefreshToken', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- logoffRevocationService,
- 'revokeRefreshToken'
- ).and.returnValue(of(null));
+ const spy = vi
+ .spyOn(logoffRevocationService, 'revokeRefreshToken')
+ .mockReturnValue(of(null));
oidcSecurityService.revokeRefreshToken().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
- }));
+ });
- it('calls logoffRevocationService.revokeRefreshToken with refresh token', waitForAsync(() => {
+ it('calls logoffRevocationService.revokeRefreshToken with refresh token', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(
- logoffRevocationService,
- 'revokeRefreshToken'
- ).and.returnValue(of(null));
+ const spy = vi
+ .spyOn(logoffRevocationService, 'revokeRefreshToken')
+ .mockReturnValue(of(null));
oidcSecurityService.revokeRefreshToken('refresh_token').subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, 'refresh_token');
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'refresh_token');
});
- }));
+ });
});
describe('getEndSessionUrl', () => {
- it('calls logoffRevocationService.getEndSessionUrl ', waitForAsync(() => {
+ it('calls logoffRevocationService.getEndSessionUrl ', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(urlService, 'getEndSessionUrl').and.returnValue(null);
+ const spy = vi
+ .spyOn(urlService, 'getEndSessionUrl')
+ .mockReturnValue(null);
oidcSecurityService.getEndSessionUrl().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
- }));
+ });
- it('calls logoffRevocationService.getEndSessionUrl with customparams', waitForAsync(() => {
+ it('calls logoffRevocationService.getEndSessionUrl with customparams', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(urlService, 'getEndSessionUrl').and.returnValue(null);
+ const spy = vi
+ .spyOn(urlService, 'getEndSessionUrl')
+ .mockReturnValue(null);
oidcSecurityService
.getEndSessionUrl({ custom: 'params' })
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, { custom: 'params' });
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
+ custom: 'params',
+ });
});
- }));
+ });
});
describe('getAuthorizeUrl', () => {
- it('calls urlService.getAuthorizeUrl ', waitForAsync(() => {
+ it('calls urlService.getAuthorizeUrl ', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(urlService, 'getAuthorizeUrl').and.returnValue(
- of(null)
- );
+ const spy = vi
+ .spyOn(urlService, 'getAuthorizeUrl')
+ .mockReturnValue(of(null));
oidcSecurityService.getAuthorizeUrl().subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, undefined);
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
- }));
+ });
- it('calls urlService.getAuthorizeUrl with customparams', waitForAsync(() => {
+ it('calls urlService.getAuthorizeUrl with customparams', async () => {
const config = { configId: 'configId1' };
- spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
+ vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
of(config)
);
- const spy = spyOn(urlService, 'getAuthorizeUrl').and.returnValue(
- of(null)
- );
+ const spy = vi
+ .spyOn(urlService, 'getAuthorizeUrl')
+ .mockReturnValue(of(null));
oidcSecurityService
.getAuthorizeUrl({ custom: 'params' })
.subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(config, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { custom: 'params' },
});
});
- }));
+ });
});
});
diff --git a/src/oidc.security.service.ts b/src/oidc.security.service.ts
index e3eb186..c9bd3ed 100644
--- a/src/oidc.security.service.ts
+++ b/src/oidc.security.service.ts
@@ -1,28 +1,28 @@
-import { inject, Injectable } from 'injection-js';
-import { Observable } from 'rxjs';
-import { concatMap, map } from 'rxjs/operators';
-import { AuthOptions, LogoutAuthOptions } from './auth-options';
-import { AuthenticatedResult } from './auth-state/auth-result';
+import { Injectable, inject } from 'injection-js';
+import { toSignal } from 'injection-js/rxjs-interop';
+import type { Observable } from 'rxjs';
+import { concatMap, map, shareReplay } from 'rxjs/operators';
+import type { AuthOptions, LogoutAuthOptions } from './auth-options';
+import type { AuthenticatedResult } from './auth-state/auth-result';
import { AuthStateService } from './auth-state/auth-state.service';
import { CheckAuthService } from './auth-state/check-auth.service';
import { CallbackService } from './callback/callback.service';
import { RefreshSessionService } from './callback/refresh-session.service';
-import { AuthWellKnownEndpoints } from './config/auth-well-known/auth-well-known-endpoints';
+import type { AuthWellKnownEndpoints } from './config/auth-well-known/auth-well-known-endpoints';
import { AuthWellKnownService } from './config/auth-well-known/auth-well-known.service';
import { ConfigurationService } from './config/config.service';
-import { OpenIdConfiguration } from './config/openid-configuration';
-import { AuthResult } from './flows/callback-context';
+import type { OpenIdConfiguration } from './config/openid-configuration';
+import type { AuthResult } from './flows/callback-context';
import { FlowsDataService } from './flows/flows-data.service';
import { CheckSessionService } from './iframe/check-session.service';
-import { LoginResponse } from './login/login-response';
+import type { LoginResponse } from './login/login-response';
import { LoginService } from './login/login.service';
-import { PopupOptions } from './login/popup/popup-options';
+import type { PopupOptions } from './login/popup/popup-options';
import { LogoffRevocationService } from './logoff-revoke/logoff-revocation.service';
import { UserService } from './user-data/user.service';
-import { UserDataResult } from './user-data/userdata-result';
+import type { UserDataResult } from './user-data/userdata-result';
import { TokenHelperService } from './utils/tokenHelper/token-helper.service';
import { UrlService } from './utils/url/url.service';
-import { toSignal } from 'injection-js/rxjs-interop';
@Injectable()
export class OidcSecurityService {
@@ -355,10 +355,17 @@ export class OidcSecurityService {
* @param configId The configId to perform the action in behalf of. If not passed, the first configs will be taken
* @param authOptions The custom options for the the authentication request.
*/
- authorize(configId?: string, authOptions?: AuthOptions): void {
- this.configurationService
+ authorize(configId?: string, authOptions?: AuthOptions): Observable {
+ const result$ = this.configurationService
.getOpenIDConfiguration(configId)
- .subscribe((config) => this.loginService.login(config, authOptions));
+ .pipe(
+ map((config) => this.loginService.login(config, authOptions)),
+ shareReplay(1)
+ );
+
+ result$.subscribe();
+
+ return result$;
}
/**
@@ -471,24 +478,34 @@ export class OidcSecurityService {
*
* @param configId The configId to perform the action in behalf of. If not passed, the first configs will be taken
*/
- logoffLocal(configId?: string): void {
- this.configurationService
+ logoffLocal(configId?: string): Observable {
+ const result$ = this.configurationService
.getOpenIDConfigurations(configId)
- .subscribe(({ allConfigs, currentConfig }) =>
- this.logoffRevocationService.logoffLocal(currentConfig, allConfigs)
+ .pipe(
+ map(({ allConfigs, currentConfig }) =>
+ this.logoffRevocationService.logoffLocal(currentConfig, allConfigs)
+ ),
+ shareReplay(1)
);
+ result$.subscribe();
+ return result$;
}
/**
* Logs the user out of the application for all configs without logging them out of the server.
* Use this method if you have _multiple_ configs enabled.
*/
- logoffLocalMultiple(): void {
- this.configurationService
- .getOpenIDConfigurations()
- .subscribe(({ allConfigs }) =>
+ logoffLocalMultiple(): Observable {
+ const result$ = this.configurationService.getOpenIDConfigurations().pipe(
+ map(({ allConfigs }) =>
this.logoffRevocationService.logoffLocalMultiple(allConfigs)
- );
+ ),
+ shareReplay(1)
+ );
+
+ result$.subscribe();
+
+ return result$;
}
/**
diff --git a/src/provide-auth.spec.ts b/src/provide-auth.spec.ts
index af0a4e0..ef27217 100644
--- a/src/provide-auth.spec.ts
+++ b/src/provide-auth.spec.ts
@@ -1,7 +1,7 @@
-import { APP_INITIALIZER } from '@angular/core';
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed, createSpyObj } from '@/testing';
+import { mockProvider } from '@/testing/mock';
+import { APP_INITIALIZER } from 'oidc-client-rx';
import { of } from 'rxjs';
-import { mockProvider } from '../test/auto-mock';
import { PASSED_CONFIG } from './auth-config';
import { ConfigurationService } from './config/config.service';
import {
@@ -14,14 +14,14 @@ import { provideAuth, withAppInitializerAuthCheck } from './provide-auth';
describe('provideAuth', () => {
describe('APP_CONFIG', () => {
- beforeEach(waitForAsync(() => {
- TestBed.configureTestingModule({
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
providers: [
provideAuth({ config: { authority: 'something' } }),
mockProvider(ConfigurationService),
],
}).compileComponents();
- }));
+ });
it('should provide config', () => {
const config = TestBed.inject(PASSED_CONFIG);
@@ -37,8 +37,8 @@ describe('provideAuth', () => {
});
describe('StsConfigHttpLoader', () => {
- beforeEach(waitForAsync(() => {
- TestBed.configureTestingModule({
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
providers: [
provideAuth({
loader: {
@@ -49,7 +49,7 @@ describe('provideAuth', () => {
mockProvider(ConfigurationService),
],
}).compileComponents();
- }));
+ });
it('should create StsConfigStaticLoader if config is passed', () => {
const configLoader = TestBed.inject(StsConfigLoader);
@@ -59,14 +59,14 @@ describe('provideAuth', () => {
});
describe('features', () => {
- let oidcSecurityServiceMock: jasmine.SpyObj;
+ let oidcSecurityServiceMock: OidcSecurityService;
- beforeEach(waitForAsync(() => {
- oidcSecurityServiceMock = jasmine.createSpyObj(
+ beforeEach(async () => {
+ oidcSecurityServiceMock = createSpyObj(
'OidcSecurityService',
['checkAuthMultiple']
);
- TestBed.configureTestingModule({
+ await TestBed.configureTestingModule({
providers: [
provideAuth(
{ config: { authority: 'something' } },
@@ -79,14 +79,15 @@ describe('provideAuth', () => {
},
],
}).compileComponents();
- }));
+ });
it('should provide APP_INITIALIZER config', () => {
const config = TestBed.inject(APP_INITIALIZER);
- expect(config.length)
- .withContext('Expected an APP_INITIALIZER to be registered')
- .toBe(1);
+ expect(
+ config.length,
+ 'Expected an APP_INITIALIZER to be registered'
+ ).toBe(1);
expect(oidcSecurityServiceMock.checkAuthMultiple).toHaveBeenCalledTimes(
1
);
diff --git a/src/provide-auth.ts b/src/provide-auth.ts
index 1730034..3f12f7f 100644
--- a/src/provide-auth.ts
+++ b/src/provide-auth.ts
@@ -1,15 +1,11 @@
+import type { Provider } from 'injection-js';
import {
- APP_INITIALIZER,
- EnvironmentProviders,
- makeEnvironmentProviders,
- Provider,
-} from 'injection-js';
-import {
- createStaticLoader,
PASSED_CONFIG,
- PassedInitialConfig,
+ type PassedInitialConfig,
+ createStaticLoader,
} from './auth-config';
import { StsConfigLoader } from './config/loader/config-loader';
+import { APP_INITIALIZER } from './injection';
import { AbstractLoggerService } from './logging/abstract-logger.service';
import { ConsoleLoggerService } from './logging/console-logger.service';
import { OidcSecurityService } from './oidc.security.service';
@@ -26,14 +22,14 @@ export interface AuthFeature {
export function provideAuth(
passedConfig: PassedInitialConfig,
...features: AuthFeature[]
-): EnvironmentProviders {
+): Provider[] {
const providers = _provideAuth(passedConfig);
for (const feature of features) {
providers.push(...feature.ɵproviders);
}
- return makeEnvironmentProviders(providers);
+ return providers;
}
export function _provideAuth(passedConfig: PassedInitialConfig): Provider[] {
diff --git a/src/public-events/event-types.ts b/src/public-events/event-types.ts
index 54f35a9..41b5bba 100644
--- a/src/public-events/event-types.ts
+++ b/src/public-events/event-types.ts
@@ -1,17 +1,18 @@
+// biome-ignore lint/nursery/noEnum:
export enum EventTypes {
/**
* This only works in the AppModule Constructor
*/
- ConfigLoaded,
- CheckingAuth,
- CheckingAuthFinished,
- CheckingAuthFinishedWithError,
- ConfigLoadingFailed,
- CheckSessionReceived,
- UserDataChanged,
- NewAuthenticationResult,
- TokenExpired,
- IdTokenExpired,
- SilentRenewStarted,
- SilentRenewFailed,
+ ConfigLoaded = 0,
+ CheckingAuth = 1,
+ CheckingAuthFinished = 2,
+ CheckingAuthFinishedWithError = 3,
+ ConfigLoadingFailed = 4,
+ CheckSessionReceived = 5,
+ UserDataChanged = 6,
+ NewAuthenticationResult = 7,
+ TokenExpired = 8,
+ IdTokenExpired = 9,
+ SilentRenewStarted = 10,
+ SilentRenewFailed = 11,
}
diff --git a/src/public-events/public-events.service.spec.ts b/src/public-events/public-events.service.spec.ts
index dcc5a78..f0e6766 100644
--- a/src/public-events/public-events.service.spec.ts
+++ b/src/public-events/public-events.service.spec.ts
@@ -1,5 +1,6 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { filter } from 'rxjs/operators';
+import { vi } from 'vitest';
import { EventTypes } from './event-types';
import { PublicEventsService } from './public-events.service';
@@ -20,7 +21,7 @@ describe('Events Service', () => {
expect(eventsService).toBeTruthy();
});
- it('registering to single event with one event emit works', waitForAsync(() => {
+ it('registering to single event with one event emit works', async () => {
eventsService.registerForEvents().subscribe((firedEvent) => {
expect(firedEvent).toBeTruthy();
expect(firedEvent).toEqual({
@@ -29,9 +30,9 @@ describe('Events Service', () => {
});
});
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
- }));
+ });
- it('registering to single event with multiple same event emit works', waitForAsync(() => {
+ it('registering to single event with multiple same event emit works', async () => {
const spy = jasmine.createSpy('spy');
eventsService.registerForEvents().subscribe((firedEvent) => {
@@ -50,9 +51,9 @@ describe('Events Service', () => {
type: EventTypes.ConfigLoaded,
value: { myKey: 'myValue2' },
});
- }));
+ });
- it('registering to single event with multiple emit works', waitForAsync(() => {
+ it('registering to single event with multiple emit works', async () => {
eventsService
.registerForEvents()
.pipe(filter((x) => x.type === EventTypes.ConfigLoaded))
@@ -65,5 +66,5 @@ describe('Events Service', () => {
});
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
eventsService.fireEvent(EventTypes.NewAuthenticationResult, true);
- }));
+ });
});
diff --git a/src/router/index.ts b/src/router/index.ts
new file mode 100644
index 0000000..c0f1f96
--- /dev/null
+++ b/src/router/index.ts
@@ -0,0 +1,27 @@
+export type RouteData = {
+ [key: string | symbol]: any;
+};
+
+export interface ActivatedRouteSnapshot {
+ data: RouteData;
+}
+
+export interface RouterStateSnapshot {
+ url: string;
+}
+
+export abstract class AbstractRouter {
+ navigateByUrl(url: string): void {
+ // TODO
+ // Implementation of navigating to a URL
+ }
+
+ getCurrentNavigation(): any {
+ // TODO
+ // Implementation of getting the current navigation
+ return null;
+ }
+
+ // TODO
+ parseUrl(url: string) {}
+}
diff --git a/src/storage/browser-storage.service.spec.ts b/src/storage/browser-storage.service.spec.ts
index e40c86e..9fa3f97 100644
--- a/src/storage/browser-storage.service.spec.ts
+++ b/src/storage/browser-storage.service.spec.ts
@@ -1,6 +1,7 @@
-import { TestBed } from '@angular/core/testing';
-import { mockClass, mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service';
+import { mockClass, mockProvider } from '../testing/mock';
import { AbstractSecurityStorage } from './abstract-security-storage';
import { BrowserStorageService } from './browser-storage.service';
import { DefaultSessionStorageService } from './default-sessionstorage.service';
@@ -34,7 +35,7 @@ describe('BrowserStorageService', () => {
it('returns null if there is no storage', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(false);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
expect(service.read('anything', config)).toBeNull();
});
@@ -42,7 +43,7 @@ describe('BrowserStorageService', () => {
it('returns null if getItem returns null', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(true);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
const result = service.read('anything', config);
@@ -52,10 +53,10 @@ describe('BrowserStorageService', () => {
it('returns the item if getItem returns an item', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(true);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
const returnValue = `{ "name":"John", "age":30, "city":"New York"}`;
- spyOn(abstractSecurityStorage, 'read').and.returnValue(returnValue);
+ vi.spyOn(abstractSecurityStorage, 'read').mockReturnValue(returnValue);
const result = service.read('anything', config);
expect(result).toEqual(JSON.parse(returnValue));
@@ -66,24 +67,21 @@ describe('BrowserStorageService', () => {
it('returns false if there is no storage', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(false);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
- expect(service.write('anyvalue', config)).toBeFalse();
+ expect(service.write('anyvalue', config)).toBeFalsy();
});
it('writes object correctly with configId', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(true);
- const writeSpy = spyOn(
- abstractSecurityStorage,
- 'write'
- ).and.callThrough();
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
+ const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
const result = service.write({ anyKey: 'anyvalue' }, config);
expect(result).toBe(true);
- expect(writeSpy).toHaveBeenCalledOnceWith(
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'configId1',
JSON.stringify({ anyKey: 'anyvalue' })
);
@@ -92,18 +90,15 @@ describe('BrowserStorageService', () => {
it('writes null if item is falsy', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(true);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
- const writeSpy = spyOn(
- abstractSecurityStorage,
- 'write'
- ).and.callThrough();
+ const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
const somethingFalsy = '';
const result = service.write(somethingFalsy, config);
expect(result).toBe(true);
- expect(writeSpy).toHaveBeenCalledOnceWith(
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'configId1',
JSON.stringify(null)
);
@@ -114,41 +109,35 @@ describe('BrowserStorageService', () => {
it('returns false if there is no storage', () => {
const config = { configId: 'configId1' };
- spyOn(service as any, 'hasStorage').and.returnValue(false);
- expect(service.remove('anything', config)).toBeFalse();
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
+ expect(service.remove('anything', config)).toBeFalsy();
});
it('returns true if removeItem is called', () => {
- spyOn(service as any, 'hasStorage').and.returnValue(true);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
const config = { configId: 'configId1' };
- const setItemSpy = spyOn(
- abstractSecurityStorage,
- 'remove'
- ).and.callThrough();
+ const setItemSpy = vi.spyOn(abstractSecurityStorage, 'remove')();
const result = service.remove('anyKey', config);
expect(result).toBe(true);
- expect(setItemSpy).toHaveBeenCalledOnceWith('anyKey');
+ expect(setItemSpy).toHaveBeenCalledExactlyOnceWith('anyKey');
});
});
describe('clear', () => {
it('returns false if there is no storage', () => {
- spyOn(service as any, 'hasStorage').and.returnValue(false);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
const config = { configId: 'configId1' };
- expect(service.clear(config)).toBeFalse();
+ expect(service.clear(config)).toBeFalsy();
});
it('returns true if clear is called', () => {
- spyOn(service as any, 'hasStorage').and.returnValue(true);
+ vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
- const setItemSpy = spyOn(
- abstractSecurityStorage,
- 'clear'
- ).and.callThrough();
+ const setItemSpy = vi.spyOn(abstractSecurityStorage, 'clear')();
const config = { configId: 'configId1' };
const result = service.clear(config);
@@ -161,7 +150,7 @@ describe('BrowserStorageService', () => {
describe('hasStorage', () => {
it('returns false if there is no storage', () => {
(Storage as any) = undefined;
- expect((service as any).hasStorage()).toBeFalse();
+ expect((service as any).hasStorage()).toBeFalsy();
Storage = Storage;
});
});
diff --git a/src/storage/default-localstorage.service.spec.ts b/src/storage/default-localstorage.service.spec.ts
index 319d609..5009d4a 100644
--- a/src/storage/default-localstorage.service.spec.ts
+++ b/src/storage/default-localstorage.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DefaultLocalStorageService } from './default-localstorage.service';
describe('DefaultLocalStorageService', () => {
@@ -20,37 +21,37 @@ describe('DefaultLocalStorageService', () => {
describe('read', () => {
it('should call localstorage.getItem', () => {
- const spy = spyOn(localStorage, 'getItem');
+ const spy = vi.spyOn(localStorage, 'getItem');
service.read('henlo');
- expect(spy).toHaveBeenCalledOnceWith('henlo');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
});
});
describe('write', () => {
it('should call localstorage.setItem', () => {
- const spy = spyOn(localStorage, 'setItem');
+ const spy = vi.spyOn(localStorage, 'setItem');
service.write('henlo', 'furiend');
- expect(spy).toHaveBeenCalledOnceWith('henlo', 'furiend');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo', 'furiend');
});
});
describe('remove', () => {
it('should call localstorage.removeItem', () => {
- const spy = spyOn(localStorage, 'removeItem');
+ const spy = vi.spyOn(localStorage, 'removeItem');
service.remove('henlo');
- expect(spy).toHaveBeenCalledOnceWith('henlo');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
});
});
describe('clear', () => {
it('should call localstorage.clear', () => {
- const spy = spyOn(localStorage, 'clear');
+ const spy = vi.spyOn(localStorage, 'clear');
service.clear();
diff --git a/src/storage/default-sessionstorage.service.spec.ts b/src/storage/default-sessionstorage.service.spec.ts
index 73f6cb6..6f904d7 100644
--- a/src/storage/default-sessionstorage.service.spec.ts
+++ b/src/storage/default-sessionstorage.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DefaultSessionStorageService } from './default-sessionstorage.service';
describe('DefaultSessionStorageService', () => {
@@ -20,37 +21,37 @@ describe('DefaultSessionStorageService', () => {
describe('read', () => {
it('should call sessionstorage.getItem', () => {
- const spy = spyOn(sessionStorage, 'getItem');
+ const spy = vi.spyOn(sessionStorage, 'getItem');
service.read('henlo');
- expect(spy).toHaveBeenCalledOnceWith('henlo');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
});
});
describe('write', () => {
it('should call sessionstorage.setItem', () => {
- const spy = spyOn(sessionStorage, 'setItem');
+ const spy = vi.spyOn(sessionStorage, 'setItem');
service.write('henlo', 'furiend');
- expect(spy).toHaveBeenCalledOnceWith('henlo', 'furiend');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo', 'furiend');
});
});
describe('remove', () => {
it('should call sessionstorage.removeItem', () => {
- const spy = spyOn(sessionStorage, 'removeItem');
+ const spy = vi.spyOn(sessionStorage, 'removeItem');
service.remove('henlo');
- expect(spy).toHaveBeenCalledOnceWith('henlo');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
});
});
describe('clear', () => {
it('should call sessionstorage.clear', () => {
- const spy = spyOn(sessionStorage, 'clear');
+ const spy = vi.spyOn(sessionStorage, 'clear');
service.clear();
diff --git a/src/storage/storage-persistence.service.spec.ts b/src/storage/storage-persistence.service.spec.ts
index 204fee1..33f77c1 100644
--- a/src/storage/storage-persistence.service.spec.ts
+++ b/src/storage/storage-persistence.service.spec.ts
@@ -1,5 +1,6 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
+import { mockProvider } from '../testing/mock';
import { BrowserStorageService } from './browser-storage.service';
import { StoragePersistenceService } from './storage-persistence.service';
@@ -25,16 +26,16 @@ describe('Storage Persistence Service', () => {
describe('read', () => {
it('reads from oidcSecurityStorage with configId', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(securityStorage, 'read');
+ const spy = vi.spyOn(securityStorage, 'read');
service.read('authNonce', config);
- expect(spy).toHaveBeenCalledOnceWith('authNonce', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
});
it('returns undefined (not throws exception) if key to read is not present on config', () => {
const config = { configId: 'configId1' };
- spyOn(securityStorage, 'read').and.returnValue({ some: 'thing' });
+ vi.spyOn(securityStorage, 'read').mockReturnValue({ some: 'thing' });
const result = service.read('authNonce', config);
expect(result).toBeUndefined();
@@ -44,13 +45,13 @@ describe('Storage Persistence Service', () => {
describe('write', () => {
it('writes to oidcSecurityStorage with correct key and correct config', () => {
const config = { configId: 'configId1' };
- const readSpy = spyOn(securityStorage, 'read');
- const writeSpy = spyOn(securityStorage, 'write');
+ const readSpy = vi.spyOn(securityStorage, 'read');
+ const writeSpy = vi.spyOn(securityStorage, 'write');
service.write('authNonce', 'anyValue', config);
- expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
- expect(writeSpy).toHaveBeenCalledOnceWith(
+ expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
{ authNonce: 'anyValue' },
config
);
@@ -60,32 +61,32 @@ describe('Storage Persistence Service', () => {
describe('remove', () => {
it('should remove key from config', () => {
const config = { configId: 'configId1' };
- const readSpy = spyOn(securityStorage, 'read').and.returnValue({
+ const readSpy = vi.spyOn(securityStorage, 'read').mockReturnValue({
authNonce: 'anyValue',
});
- const writeSpy = spyOn(securityStorage, 'write');
+ const writeSpy = vi.spyOn(securityStorage, 'write');
service.remove('authNonce', config);
- expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
- expect(writeSpy).toHaveBeenCalledOnceWith({}, config);
+ expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith({}, config);
});
it('does not crash when read with configId returns null', () => {
const config = { configId: 'configId1' };
- const readSpy = spyOn(securityStorage, 'read').and.returnValue(null);
- const writeSpy = spyOn(securityStorage, 'write');
+ const readSpy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
+ const writeSpy = vi.spyOn(securityStorage, 'write');
service.remove('authNonce', config);
- expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
- expect(writeSpy).toHaveBeenCalledOnceWith({}, config);
+ expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
+ expect(writeSpy).toHaveBeenCalledExactlyOnceWith({}, config);
});
});
describe('clear', () => {
it('should call oidcSecurityStorage.clear()', () => {
- const clearSpy = spyOn(securityStorage, 'clear');
+ const clearSpy = vi.spyOn(securityStorage, 'clear');
service.clear({});
@@ -96,49 +97,58 @@ describe('Storage Persistence Service', () => {
describe('resetStorageFlowData', () => {
it('resets the correct values', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(service, 'remove');
+ const spy = vi.spyOn(service, 'remove');
service.resetStorageFlowData(config);
expect(spy).toHaveBeenCalledTimes(10);
- expect(spy.calls.argsFor(0)).toEqual(['session_state', config]);
- expect(spy.calls.argsFor(1)).toEqual([
+ expect(vi.mocked(spy).mock.calls[0]).toEqual(['session_state', config]);
+ expect(vi.mocked(spy).mock.calls[1]).toEqual([
'storageSilentRenewRunning',
config,
]);
- expect(spy.calls.argsFor(2)).toEqual([
+ expect(vi.mocked(spy).mock.calls[2]).toEqual([
'storageCodeFlowInProgress',
config,
]);
- expect(spy.calls.argsFor(3)).toEqual(['codeVerifier', config]);
- expect(spy.calls.argsFor(4)).toEqual(['userData', config]);
- expect(spy.calls.argsFor(5)).toEqual([
+ expect(vi.mocked(spy).mock.calls[3]).toEqual(['codeVerifier', config]);
+ expect(vi.mocked(spy).mock.calls[4]).toEqual(['userData', config]);
+ expect(vi.mocked(spy).mock.calls[5]).toEqual([
'storageCustomParamsAuthRequest',
config,
]);
- expect(spy.calls.argsFor(6)).toEqual(['access_token_expires_at', config]);
- expect(spy.calls.argsFor(7)).toEqual([
+ expect(vi.mocked(spy).mock.calls[6]).toEqual([
+ 'access_token_expires_at',
+ config,
+ ]);
+ expect(vi.mocked(spy).mock.calls[7]).toEqual([
'storageCustomParamsRefresh',
config,
]);
- expect(spy.calls.argsFor(8)).toEqual([
+ expect(vi.mocked(spy).mock.calls[8]).toEqual([
'storageCustomParamsEndSession',
config,
]);
- expect(spy.calls.argsFor(9)).toEqual(['reusable_refresh_token', config]);
+ expect(vi.mocked(spy).mock.calls[9]).toEqual([
+ 'reusable_refresh_token',
+ config,
+ ]);
});
});
describe('resetAuthStateInStorage', () => {
it('resets the correct values', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(service, 'remove');
+ const spy = vi.spyOn(service, 'remove');
service.resetAuthStateInStorage(config);
- expect(spy.calls.argsFor(0)).toEqual(['authzData', config]);
- expect(spy.calls.argsFor(1)).toEqual(['reusable_refresh_token', config]);
- expect(spy.calls.argsFor(2)).toEqual(['authnResult', config]);
+ expect(vi.mocked(spy).mock.calls[0]).toEqual(['authzData', config]);
+ expect(vi.mocked(spy).mock.calls[1]).toEqual([
+ 'reusable_refresh_token',
+ config,
+ ]);
+ expect(vi.mocked(spy).mock.calls[2]).toEqual(['authnResult', config]);
});
});
@@ -146,41 +156,45 @@ describe('Storage Persistence Service', () => {
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
const returnValue = { authzData: 'someValue' };
const config = { configId: 'configId1' };
- const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
+ const spy = vi
+ .spyOn(securityStorage, 'read')
+ .mockReturnValue(returnValue);
const result = service.getAccessToken(config);
expect(result).toBe('someValue');
- expect(spy).toHaveBeenCalledOnceWith('authzData', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authzData', config);
});
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
- const spy = spyOn(securityStorage, 'read').and.returnValue(null);
+ const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
const config = { configId: 'configId1' };
const result = service.getAccessToken(config);
expect(result).toBeFalsy();
- expect(spy).toHaveBeenCalledOnceWith('authzData', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authzData', config);
});
});
describe('getIdToken', () => {
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
const returnValue = { authnResult: { id_token: 'someValue' } };
- const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
+ const spy = vi
+ .spyOn(securityStorage, 'read')
+ .mockReturnValue(returnValue);
const config = { configId: 'configId1' };
const result = service.getIdToken(config);
expect(result).toBe('someValue');
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
- const spy = spyOn(securityStorage, 'read').and.returnValue(null);
+ const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
const config = { configId: 'configId1' };
const result = service.getIdToken(config);
expect(result).toBeFalsy();
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
});
@@ -188,32 +202,36 @@ describe('Storage Persistence Service', () => {
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
const returnValue = { authnResult: { id_token: 'someValue' } };
const config = { configId: 'configId1' };
- const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
+ const spy = vi
+ .spyOn(securityStorage, 'read')
+ .mockReturnValue(returnValue);
const result = service.getAuthenticationResult(config);
expect(result.id_token).toBe('someValue');
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
- const spy = spyOn(securityStorage, 'read').and.returnValue(null);
+ const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
const config = { configId: 'configId1' };
const result = service.getAuthenticationResult(config);
expect(result).toBeFalsy();
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
});
describe('getRefreshToken', () => {
it('get calls oidcSecurityStorage.read with correct key and returns the value (refresh token with mandatory rotation - default)', () => {
const returnValue = { authnResult: { refresh_token: 'someValue' } };
- const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
+ const spy = vi
+ .spyOn(securityStorage, 'read')
+ .mockReturnValue(returnValue);
const config = { configId: 'configId1' };
const result = service.getRefreshToken(config);
expect(result).toBe('someValue');
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
it('get calls oidcSecurityStorage.read with correct key and returns the value (refresh token without rotation)', () => {
@@ -222,12 +240,12 @@ describe('Storage Persistence Service', () => {
configId: 'configId1',
allowUnsafeReuseRefreshToken: true,
};
- const spy = spyOn(securityStorage, 'read');
+ const spy = vi.spyOn(securityStorage, 'read');
spy
.withArgs('reusable_refresh_token', config)
- .and.returnValue(returnValue);
- spy.withArgs('authnResult', config).and.returnValue(undefined);
+ .mockReturnValue(returnValue);
+ spy.withArgs('authnResult', config).mockReturnValue(undefined);
const result = service.getRefreshToken(config);
expect(result).toBe(returnValue.reusable_refresh_token);
@@ -238,21 +256,23 @@ describe('Storage Persistence Service', () => {
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
const returnValue = { authnResult: { NO_refresh_token: 'someValue' } };
- const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
+ const spy = vi
+ .spyOn(securityStorage, 'read')
+ .mockReturnValue(returnValue);
const config = { configId: 'configId1' };
const result = service.getRefreshToken(config);
expect(result).toBeUndefined();
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
- const spy = spyOn(securityStorage, 'read').and.returnValue(null);
+ const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
const config = { configId: 'configId1' };
const result = service.getRefreshToken(config);
expect(result).toBeUndefined();
- expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
});
});
});
diff --git a/src/storage/storage-persistence.service.ts b/src/storage/storage-persistence.service.ts
index 5f1cea2..ea1adf9 100644
--- a/src/storage/storage-persistence.service.ts
+++ b/src/storage/storage-persistence.service.ts
@@ -1,6 +1,6 @@
-import { inject, Injectable } from 'injection-js';
-import { AuthResult } from '../flows/callback-context';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import { inject } from 'injection-js';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { AuthResult } from '../flows/callback-context';
import { BrowserStorageService } from './browser-storage.service';
export type StorageKeys =
@@ -24,7 +24,6 @@ export type StorageKeys =
| 'jwtKeys'
| 'popupauth';
-
export class StoragePersistenceService {
private readonly browserStorageService = inject(BrowserStorageService);
diff --git a/test/create-retriable-stream.helper.ts b/src/testing/create-retriable-stream.helper.ts
similarity index 84%
rename from test/create-retriable-stream.helper.ts
rename to src/testing/create-retriable-stream.helper.ts
index ec6fa36..6b339de 100644
--- a/test/create-retriable-stream.helper.ts
+++ b/src/testing/create-retriable-stream.helper.ts
@@ -1,4 +1,4 @@
-import { Observable, of } from 'rxjs';
+import { type Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
// Create retriable observable stream to test retry / retryWhen. Credits to:
@@ -6,7 +6,7 @@ import { switchMap } from 'rxjs/operators';
export const createRetriableStream = (...resp$: any): Observable => {
const fetchData: jasmine.Spy = jasmine.createSpy('fetchData');
- fetchData.and.returnValues(...resp$);
+ fetchData.mockReturnValues(...resp$);
return of(null).pipe(switchMap((_) => fetchData()));
};
diff --git a/src/testing/index.ts b/src/testing/index.ts
new file mode 100644
index 0000000..37fb2b2
--- /dev/null
+++ b/src/testing/index.ts
@@ -0,0 +1,7 @@
+export { TestBed } from './testbed';
+export {
+ createSpyObj,
+ mockImplementationWhenArgsEqual,
+} from './spy';
+export { createRetriableStream } from './create-retriable-stream.helper';
+export { MockRouter, mockRouterProvider } from './router';
diff --git a/src/test.ts b/src/testing/init-test.ts
similarity index 63%
rename from src/test.ts
rename to src/testing/init-test.ts
index b4d91d6..8de1e00 100644
--- a/src/test.ts
+++ b/src/testing/init-test.ts
@@ -1,8 +1,4 @@
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'zone.js';
-import 'zone.js/testing';
-import { getTestBed } from 'injection-js/testing';
+import { getTestBed } from '@/testing/testbed';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
diff --git a/test/auto-mock.ts b/src/testing/mock.ts
similarity index 78%
rename from test/auto-mock.ts
rename to src/testing/mock.ts
index 231ba4a..cc9f692 100644
--- a/test/auto-mock.ts
+++ b/src/testing/mock.ts
@@ -1,11 +1,11 @@
-import { Provider } from 'injection-js';
+import type { Provider } from 'injection-js';
export function mockClass(obj: new (...args: any[]) => T): any {
const keys = Object.getOwnPropertyNames(obj.prototype);
const allMethods = keys.filter((key) => {
try {
return typeof obj.prototype[key] === 'function';
- } catch (error) {
+ } catch {
return false;
}
});
@@ -13,21 +13,20 @@ export function mockClass(obj: new (...args: any[]) => T): any {
const mockedClass = class T {};
- allMethods.forEach(
- (method: string) =>
- ((mockedClass.prototype as any)[method] = (): void => {
- return;
- })
- );
+ for (const method of allMethods) {
+ (mockedClass.prototype as any)[method] = (): void => {
+ return;
+ };
+ }
- allProperties.forEach((method) => {
+ for (const method of allProperties) {
Object.defineProperty(mockedClass.prototype, method, {
get() {
return '';
},
configurable: true,
});
- });
+ }
return mockedClass;
}
diff --git a/src/testing/router.ts b/src/testing/router.ts
new file mode 100644
index 0000000..908b70c
--- /dev/null
+++ b/src/testing/router.ts
@@ -0,0 +1,12 @@
+import type { Provider } from 'injection-js';
+import { AbstractRouter } from 'oidc-client-rx';
+
+// TODO
+export class MockRouter extends AbstractRouter {}
+
+export function mockRouterProvider(): Provider {
+ return {
+ useClass: MockRouter,
+ provide: AbstractRouter, // This is the token that will be injected into components
+ };
+}
diff --git a/src/testing/spy.ts b/src/testing/spy.ts
new file mode 100644
index 0000000..5cdaa9b
--- /dev/null
+++ b/src/testing/spy.ts
@@ -0,0 +1,53 @@
+import { isEqual } from 'lodash-es';
+import { type MockInstance, vi } from 'vitest';
+
+export function createSpyObj(baseName: string, methods: (keyof T)[]): T {
+ const SpyClass = new Function(
+ `return class Spy${baseName} {
+ constructor() {}
+ }`
+ ) as new () => T;
+
+ const spyObj = new SpyClass();
+
+ for (const method of methods) {
+ Object.defineProperty(spyObj, method, {
+ value: vi.fn(),
+ writable: true,
+ });
+ }
+
+ return spyObj;
+}
+
+export function mockImplementationWhenArgsEqual>(
+ mockInstance: M,
+ whenArgs: Parameters ? T : never>,
+ implementation: Exclude, undefined>
+): M {
+ const spyImpl = mockInstance.getMockImplementation()!;
+
+ return mockInstance.mockImplementation((...args) => {
+ if (isEqual(args, whenArgs)) {
+ return implementation(...args);
+ }
+ return spyImpl?.(...args);
+ });
+}
+
+export function mockImplementationWhenArgs>(
+ mockInstance: M,
+ whenArgs: (
+ ...args: Parameters ? T : never>
+ ) => boolean,
+ implementation: Exclude, undefined>
+): M {
+ const spyImpl = mockInstance.getMockImplementation()!;
+
+ return mockInstance.mockImplementation((...args) => {
+ if (isEqual(args, whenArgs)) {
+ return implementation(...args);
+ }
+ return spyImpl?.(...args);
+ });
+}
diff --git a/src/testing/testbed.ts b/src/testing/testbed.ts
new file mode 100644
index 0000000..1339522
--- /dev/null
+++ b/src/testing/testbed.ts
@@ -0,0 +1,90 @@
+import {
+ type InjectionToken,
+ type Injector,
+ type Provider,
+ ReflectiveInjector,
+ type Type,
+} from 'injection-js';
+import { setCurrentInjector } from 'injection-js/lib/injector_compatibility';
+
+export interface TestModuleMetadata {
+ providers?: Provider[];
+ imports?: ((parentInjector: Injector) => Injector)[];
+}
+
+export class TestBed {
+ private injector: ReflectiveInjector;
+ private providers: Provider[] = [];
+ private imports: Injector[] = [];
+
+ constructor(metadata: TestModuleMetadata = {}) {
+ const providers = metadata.providers ?? [];
+ const imports = metadata.imports ?? [];
+ this.injector = ReflectiveInjector.resolveAndCreate(providers);
+ this.imports = imports.map((importFn) => importFn(this.injector));
+ }
+
+ static #instance?: TestBed;
+
+ static configureTestingModule(metadata: TestModuleMetadata = {}) {
+ const newTestBed = new TestBed(metadata);
+ TestBed.#instance = newTestBed;
+
+ return newTestBed;
+ }
+
+ /**
+ * 在 TestBed 的注入上下文中运行函数
+ */
+ static runInInjectionContext(fn: () => T): T {
+ const injector = TestBed.#instance?.injector;
+ if (!injector) {
+ throw new Error(
+ 'TestBed is not configured. Call configureTestingModule first.'
+ );
+ }
+
+ // 保存当前的注入器
+ const previousInjector = setCurrentInjector(injector);
+
+ try {
+ // 在注入上下文中执行函数
+ return fn();
+ } finally {
+ // 恢复之前的注入器
+ setCurrentInjector(previousInjector);
+ }
+ }
+
+ compileComponents(): Promise {
+ return Promise.resolve();
+ }
+
+ static get instance(): TestBed {
+ if (!TestBed.#instance) {
+ throw new Error('TestBest.configureTestingModule should be called first');
+ }
+ return TestBed.#instance;
+ }
+
+ static get(token: Type | InjectionToken): T;
+ static get(token: any): any;
+ static get(token: unknown): any {
+ const g = TestBed.instance;
+ return g.injector.get(token);
+ }
+
+ static inject(token: Type | InjectionToken): T;
+ static inject(token: any): any;
+ static inject(token: unknown): any {
+ return TestBed.get(token as any);
+ }
+
+ static [Symbol.dispose]() {
+ TestBed.#instance = undefined;
+ }
+}
+
+export function getTestBed() {
+ return TestBed.instance;
+}
diff --git a/src/user-data/user-service.spec.ts b/src/user-data/user-service.spec.ts
index bdf8210..f525ade 100644
--- a/src/user-data/user-service.spec.ts
+++ b/src/user-data/user-service.spec.ts
@@ -1,13 +1,14 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { Observable, of, throwError } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { createRetriableStream } from '../../test/create-retriable-stream.helper';
+import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
+import { Observable, lastValueFrom, of, throwError } from 'rxjs';
+import { vi } from 'vitest';
import { DataService } from '../api/data.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { createRetriableStream } from '../testing/create-retriable-stream.helper';
+import { mockProvider } from '../testing/mock';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
@@ -38,9 +39,6 @@ describe('User Service', () => {
FlowHelper,
],
});
- });
-
- beforeEach(() => {
loggerService = TestBed.inject(LoggerService);
userService = TestBed.inject(UserService);
storagePersistenceService = TestBed.inject(StoragePersistenceService);
@@ -53,11 +51,11 @@ describe('User Service', () => {
});
it('public authorize$ is observable$', () => {
- expect(userService.userData$).toEqual(jasmine.any(Observable));
+ expect(userService.userData$).toBeInstanceOf(Observable);
});
describe('getAndPersistUserDataInStore', () => {
- it('if not currentFlow is NOT id Token or Code flow, return decoded ID Token - passed as argument', waitForAsync(() => {
+ it('if not currentFlow is NOT id Token or Code flow, return decoded ID Token - passed as argument', async () => {
const isRenewProcess = false;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -68,24 +66,24 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(decodedIdToken).toBe(token);
- });
- }));
+ );
- it('if not currentFlow is NOT id Token or Code flow, "setUserDataToStore" is called with the decodedIdToken', waitForAsync(() => {
+ expect(decodedIdToken).toBe(token);
+ });
+
+ it('if not currentFlow is NOT id Token or Code flow, "setUserDataToStore" is called with the decodedIdToken', async () => {
const isRenewProcess = false;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -96,27 +94,27 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- spyOn(userService, 'setUserDataToStore');
+ vi.spyOn(userService, 'setUserDataToStore');
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(decodedIdToken).toBe(token);
- });
+ );
+
+ expect(decodedIdToken).toBe(token);
expect(userService.setUserDataToStore).toHaveBeenCalled();
- }));
+ });
- it('if not currentFlow is id token or code flow with renewProcess going -> return existing data from storage', waitForAsync(() => {
+ it('if not currentFlow is id token or code flow with renewProcess going -> return existing data from storage', async () => {
const isRenewProcess = true;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -127,24 +125,24 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(userDataInstore).toBe(token);
- });
- }));
+ );
- it('if not currentFlow is id token or code flow and not renewProcess --> ask server for data', waitForAsync(() => {
+ expect(userDataInstore).toBe(token);
+ });
+
+ it('if not currentFlow is id token or code flow and not renewProcess --> ask server for data', async () => {
const isRenewProcess = false;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -156,32 +154,31 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- const spy = spyOn(
- userService as any,
- 'getIdentityUserData'
- ).and.returnValue(of(userDataFromSts));
+ const spy = vi
+ .spyOn(userService as any, 'getIdentityUserData')
+ .mockReturnValue(of(userDataFromSts));
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(userDataFromSts).toEqual(token);
- });
+ );
+
+ expect(userDataFromSts).toEqual(token);
expect(spy).toHaveBeenCalled();
- }));
+ });
it(`if not currentFlow is id token or code flow and not renewprocess
--> ask server for data
- --> logging if it has userdata`, waitForAsync(() => {
+ --> logging if it has userdata`, async () => {
const isRenewProcess = false;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -193,38 +190,37 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- const spy = spyOn(
- userService as any,
- 'getIdentityUserData'
- ).and.returnValue(of(userDataFromSts));
+ const spy = vi
+ .spyOn(userService as any, 'getIdentityUserData')
+ .mockReturnValue(of(userDataFromSts));
- spyOn(loggerService, 'logDebug');
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(loggerService, 'logDebug');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(userDataFromSts).toEqual(token);
- });
+ );
+
+ expect(userDataFromSts).toEqual(token);
expect(spy).toHaveBeenCalled();
expect(loggerService.logDebug).toHaveBeenCalled();
- }));
+ });
it(`if not currentFlow is id token or code flow and not renewprocess
--> ask server for data
- --> throwing Error if it has no userdata `, waitForAsync(() => {
+ --> throwing Error if it has no userdata `, async () => {
const isRenewProcess = false;
const idToken = '';
const decodedIdToken = { sub: 'decodedIdToken' };
@@ -236,40 +232,37 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- const spyGetIdentityUserData = spyOn(
- userService as any,
- 'getIdentityUserData'
- ).and.returnValue(of(userDataFromSts));
+ const spyGetIdentityUserData = vi
+ .spyOn(userService as any, 'getIdentityUserData')
+ .mockReturnValue(of(userDataFromSts));
- spyOn(loggerService, 'logDebug');
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(loggerService, 'logDebug');
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- userService
- .getAndPersistUserDataInStore(
- config,
- [config],
- isRenewProcess,
- idToken,
- decodedIdToken
- )
- .subscribe({
- error: (err) => {
- expect(err.message).toEqual(
- 'Received no user data, request failed'
- );
- },
- });
+ try {
+ await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
+ config,
+ [config],
+ isRenewProcess,
+ idToken,
+ decodedIdToken
+ )
+ );
+ } catch (err: any) {
+ expect(err.message).toEqual('Received no user data, request failed');
+ }
expect(spyGetIdentityUserData).toHaveBeenCalled();
- }));
+ });
it(`if not currentFlow is id token or code flow and renewprocess and renewUserInfoAfterTokenRenew
- --> ask server for data`, waitForAsync(() => {
+ --> ask server for data`, async () => {
const isRenewProcess = true;
const idToken = '';
const decodedIdToken = 'decodedIdToken';
@@ -282,28 +275,26 @@ describe('User Service', () => {
configId: 'configId1',
} as OpenIdConfiguration;
- spyOn(userService, 'getUserDataFromStore').and.returnValue(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
userDataInstore
);
- const spy = spyOn(
- userService as any,
- 'getIdentityUserData'
- ).and.returnValue(of(userDataFromSts));
+ const spy = vi
+ .spyOn(userService as any, 'getIdentityUserData')
+ .mockReturnValue(of(userDataFromSts));
- userService
- .getAndPersistUserDataInStore(
+ const token = await lastValueFrom(
+ userService.getAndPersistUserDataInStore(
config,
[config],
isRenewProcess,
idToken,
decodedIdToken
)
- .subscribe((token) => {
- expect(userDataFromSts).toEqual(token);
- });
+ );
+ expect(userDataFromSts).toEqual(token);
expect(spy).toHaveBeenCalled();
- }));
+ });
});
describe('getUserDataFromStore', () => {
@@ -317,9 +308,11 @@ describe('User Service', () => {
it('returns value if there is data', () => {
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('userData', config)
- .and.returnValue('userData');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['userData', config],
+ () => 'userData'
+ );
const result = userService.getUserDataFromStore(config);
expect(result).toBeTruthy();
@@ -329,10 +322,10 @@ describe('User Service', () => {
describe('setUserDataToStore', () => {
it('sets userData in storagePersistenceService', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(storagePersistenceService, 'write');
+ const spy = vi.spyOn(storagePersistenceService, 'write');
userService.setUserDataToStore('userDataForTest', config, [config]);
- expect(spy).toHaveBeenCalledOnceWith(
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
'userData',
'userDataForTest',
config
@@ -342,11 +335,11 @@ describe('User Service', () => {
it('userDataInternal$ is called when userData is set', () => {
const config = { configId: 'configId1' };
- const spy = spyOn((userService as any).userDataInternal$, 'next');
+ const spy = vi.spyOn((userService as any).userDataInternal$, 'next');
userService.setUserDataToStore('userDataForTest', config, [config]);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
userData: 'userDataForTest',
allUserData: [{ configId: 'configId1', userData: 'userDataForTest' }],
});
@@ -354,11 +347,11 @@ describe('User Service', () => {
it('eventService.fireEvent is called when userData is set', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(eventsService, 'fireEvent');
+ const spy = vi.spyOn(eventsService, 'fireEvent');
userService.setUserDataToStore('userDataForTest', config, [config]);
- expect(spy).toHaveBeenCalledOnceWith(EventTypes.UserDataChanged, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(EventTypes.UserDataChanged, {
configId: 'configId1',
userData: 'userDataForTest',
});
@@ -368,20 +361,20 @@ describe('User Service', () => {
describe('resetUserDataInStore', () => {
it('resets userData sets null in storagePersistenceService', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(storagePersistenceService, 'remove');
+ const spy = vi.spyOn(storagePersistenceService, 'remove');
userService.resetUserDataInStore(config, [config]);
- expect(spy).toHaveBeenCalledOnceWith('userData', config);
+ expect(spy).toHaveBeenCalledExactlyOnceWith('userData', config);
});
it('userDataInternal$ is called with null when userData is reset', () => {
const config = { configId: 'configId1' };
- const spy = spyOn((userService as any).userDataInternal$, 'next');
+ const spy = vi.spyOn((userService as any).userDataInternal$, 'next');
userService.resetUserDataInStore(config, [config]);
- expect(spy).toHaveBeenCalledOnceWith({
+ expect(spy).toHaveBeenCalledExactlyOnceWith({
userData: null,
allUserData: [{ configId: 'configId1', userData: null }],
});
@@ -389,11 +382,11 @@ describe('User Service', () => {
it('eventService.fireEvent is called with null when userData is reset', () => {
const config = { configId: 'configId1' };
- const spy = spyOn(eventsService, 'fireEvent');
+ const spy = vi.spyOn(eventsService, 'fireEvent');
userService.resetUserDataInStore(config, [config]);
- expect(spy).toHaveBeenCalledOnceWith(EventTypes.UserDataChanged, {
+ expect(spy).toHaveBeenCalledExactlyOnceWith(EventTypes.UserDataChanged, {
configId: 'configId1',
userData: null,
});
@@ -402,12 +395,12 @@ describe('User Service', () => {
describe('publishUserDataIfExists', () => {
it('do nothing if no userData is stored', () => {
- spyOn(userService, 'getUserDataFromStore').and.returnValue('');
- const observableSpy = spyOn(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue('');
+ const observableSpy = vi.spyOn(
(userService as any).userDataInternal$,
'next'
);
- const eventSpy = spyOn(eventsService, 'fireEvent');
+ const eventSpy = vi.spyOn(eventsService, 'fireEvent');
const config = { configId: 'configId1' };
userService.publishUserDataIfExists(config, [config]);
@@ -417,8 +410,10 @@ describe('User Service', () => {
});
it('userDataInternal is fired if userData exists with single config', () => {
- spyOn(userService, 'getUserDataFromStore').and.returnValue('something');
- const observableSpy = spyOn(
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
+ 'something'
+ );
+ const observableSpy = vi.spyOn(
(userService as any).userDataInternal$,
'next'
);
@@ -426,7 +421,7 @@ describe('User Service', () => {
userService.publishUserDataIfExists(config, [config]);
- expect(observableSpy).toHaveBeenCalledOnceWith({
+ expect(observableSpy).toHaveBeenCalledExactlyOnceWith({
userData: 'something',
allUserData: [{ configId: 'configId1', userData: 'something' }],
});
@@ -434,20 +429,24 @@ describe('User Service', () => {
it('userDataInternal is fired if userData exists with multiple configs', () => {
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
- const observableSpy = spyOn(
+ const observableSpy = vi.spyOn(
(userService as any).userDataInternal$,
'next'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('userData', allConfigs[0])
- .and.returnValue('somethingForConfig1')
- .withArgs('userData', allConfigs[1])
- .and.returnValue('somethingForConfig2');
+ mockImplementationWhenArgsEqual(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['userData', allConfigs[0]!],
+ () => 'somethingForConfig1'
+ ),
+ ['userData', allConfigs[1]!],
+ () => 'somethingForConfig2'
+ );
- userService.publishUserDataIfExists(allConfigs[0], allConfigs);
+ userService.publishUserDataIfExists(allConfigs[0]!, allConfigs);
- expect(observableSpy).toHaveBeenCalledOnceWith({
+ expect(observableSpy).toHaveBeenCalledExactlyOnceWith({
userData: null,
allUserData: [
{ configId: 'configId1', userData: 'somethingForConfig1' },
@@ -459,15 +458,20 @@ describe('User Service', () => {
it('event service UserDataChanged is fired if userData exists', () => {
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
- spyOn(userService, 'getUserDataFromStore').and.returnValue('something');
- const eventSpy = spyOn(eventsService, 'fireEvent');
+ vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
+ 'something'
+ );
+ const eventSpy = vi.spyOn(eventsService, 'fireEvent');
- userService.publishUserDataIfExists(allConfigs[0], allConfigs);
+ userService.publishUserDataIfExists(allConfigs[0]!, allConfigs);
- expect(eventSpy).toHaveBeenCalledOnceWith(EventTypes.UserDataChanged, {
- configId: 'configId1',
- userData: 'something',
- });
+ expect(eventSpy).toHaveBeenCalledExactlyOnceWith(
+ EventTypes.UserDataChanged,
+ {
+ configId: 'configId1',
+ userData: 'something',
+ }
+ );
});
});
@@ -482,7 +486,7 @@ describe('User Service', () => {
'anything'
);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('with no userDataSub returns false', () => {
@@ -495,12 +499,12 @@ describe('User Service', () => {
''
);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('with idTokenSub and userDataSub not match logs and returns false', () => {
const serviceAsAny = userService as any;
- const loggerSpy = spyOn(loggerService, 'logDebug');
+ const loggerSpy = vi.spyOn(loggerService, 'logDebug');
const config = { configId: 'configId1' };
const result = serviceAsAny.validateUserDataSubIdToken(
@@ -509,8 +513,8 @@ describe('User Service', () => {
'something2'
);
- expect(result).toBeFalse();
- expect(loggerSpy).toHaveBeenCalledOnceWith(
+ expect(result).toBeFalsy();
+ expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
config,
'validateUserDataSubIdToken failed',
'something',
@@ -520,95 +524,108 @@ describe('User Service', () => {
});
describe('getIdentityUserData', () => {
- it('does nothing if no authWellKnownEndPoints are set', waitForAsync(() => {
+ it('does nothing if no authWellKnownEndPoints are set', async () => {
const config = { configId: 'configId1' };
const serviceAsAny = userService as any;
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
- serviceAsAny.getIdentityUserData(config).subscribe({
- error: (err: any) => {
- expect(err).toBeTruthy();
- },
- });
- }));
- it('does nothing if no userInfoEndpoint is set', waitForAsync(() => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
+ try {
+ await lastValueFrom(serviceAsAny.getIdentityUserData(config));
+ } catch (err: any) {
+ expect(err).toBeTruthy();
+ }
+ });
+
+ it('does nothing if no userInfoEndpoint is set', async () => {
const config = { configId: 'configId1' };
const serviceAsAny = userService as any;
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ userInfoEndpoint: null });
- serviceAsAny.getIdentityUserData(config).subscribe({
- error: (err: any) => {
- expect(err).toBeTruthy();
- },
- });
- }));
- it('gets userData if authwell and userInfoEndpoint is set', waitForAsync(() => {
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ userInfoEndpoint: null })
+ );
+
+ try {
+ await lastValueFrom(serviceAsAny.getIdentityUserData(config));
+ } catch (err: any) {
+ expect(err).toBeTruthy();
+ }
+ });
+
+ it('gets userData if authwell and userInfoEndpoint is set', async () => {
const config = { configId: 'configId1' };
const serviceAsAny = userService as any;
- const spy = spyOn(dataService, 'get').and.returnValue(of({}));
+ const spy = vi.spyOn(dataService, 'get').mockReturnValue(of({}));
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ userInfoEndpoint: 'userInfoEndpoint' });
- serviceAsAny.getIdentityUserData(config).subscribe(() => {
- expect(spy).toHaveBeenCalledOnceWith(
- 'userInfoEndpoint',
- config,
- 'accessToken'
- );
- });
- }));
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ userInfoEndpoint: 'userInfoEndpoint' })
+ );
+
+ await lastValueFrom(serviceAsAny.getIdentityUserData(config));
+ expect(spy).toHaveBeenCalledExactlyOnceWith(
+ 'userInfoEndpoint',
+ config,
+ 'accessToken'
+ );
+ });
});
- it('should retry once', waitForAsync(() => {
+ it('should retry once', async () => {
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ userInfoEndpoint: 'userInfoEndpoint' });
- spyOn(dataService, 'get').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ userInfoEndpoint: 'userInfoEndpoint' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
of(DUMMY_USER_DATA)
)
);
- (userService as any).getIdentityUserData(config).subscribe({
- next: (res: any) => {
- expect(res).toBeTruthy();
- expect(res).toEqual(DUMMY_USER_DATA);
- },
- });
- }));
+ const res = await lastValueFrom(
+ (userService as any).getIdentityUserData(config)
+ );
- it('should retry twice', waitForAsync(() => {
+ expect(res).toBeTruthy();
+ expect(res).toEqual(DUMMY_USER_DATA);
+ });
+
+ it('should retry twice', async () => {
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ userInfoEndpoint: 'userInfoEndpoint' });
- spyOn(dataService, 'get').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ userInfoEndpoint: 'userInfoEndpoint' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -616,24 +633,25 @@ describe('User Service', () => {
)
);
- (userService as any).getIdentityUserData(config).subscribe({
- next: (res: any) => {
- expect(res).toBeTruthy();
- expect(res).toEqual(DUMMY_USER_DATA);
- },
- });
- }));
+ const res = await lastValueFrom(
+ (userService as any).getIdentityUserData(config)
+ );
+ expect(res).toBeTruthy();
+ expect(res).toEqual(DUMMY_USER_DATA);
+ });
- it('should fail after three tries', waitForAsync(() => {
+ it('should fail after three tries', async () => {
const config = { configId: 'configId1' };
- spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
+ vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
'accessToken'
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ userInfoEndpoint: 'userInfoEndpoint' });
- spyOn(dataService, 'get').and.returnValue(
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ userInfoEndpoint: 'userInfoEndpoint' })
+ );
+ vi.spyOn(dataService, 'get').mockReturnValue(
createRetriableStream(
throwError(() => new Error('Error')),
throwError(() => new Error('Error')),
@@ -642,10 +660,10 @@ describe('User Service', () => {
)
);
- (userService as any).getIdentityUserData(config).subscribe({
- error: (err: any) => {
- expect(err).toBeTruthy();
- },
- });
- }));
+ try {
+ await lastValueFrom((userService as any).getIdentityUserData(config));
+ } catch (err: any) {
+ expect(err).toBeTruthy();
+ }
+ });
});
diff --git a/src/user-data/user.service.ts b/src/user-data/user.service.ts
index 2ef4653..4d2597c 100644
--- a/src/user-data/user.service.ts
+++ b/src/user-data/user.service.ts
@@ -1,15 +1,15 @@
-import { inject, Injectable } from 'injection-js';
-import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
+import { Injectable, inject } from 'injection-js';
+import { BehaviorSubject, type Observable, of, throwError } from 'rxjs';
import { map, retry, switchMap } from 'rxjs/operators';
import { DataService } from '../api/data.service';
-import { OpenIdConfiguration } from '../config/openid-configuration';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
-import { ConfigUserDataResult, UserDataResult } from './userdata-result';
+import type { ConfigUserDataResult, UserDataResult } from './userdata-result';
const DEFAULT_USERRESULT = { userData: null, allUserData: [] };
@@ -44,13 +44,13 @@ export class UserService {
idToken?: string,
decodedIdToken?: any
): Observable {
- idToken =
+ const _idToken =
idToken ||
this.storagePersistenceService.getIdToken(currentConfiguration);
- decodedIdToken =
+ const _decodedIdToken =
decodedIdToken ||
this.tokenHelperService.getPayloadFromToken(
- idToken,
+ _idToken,
false,
currentConfiguration
);
@@ -74,16 +74,20 @@ export class UserService {
`authCallback idToken flow with accessToken ${accessToken}`
);
- this.setUserDataToStore(decodedIdToken, currentConfiguration, allConfigs);
+ this.setUserDataToStore(
+ _decodedIdToken,
+ currentConfiguration,
+ allConfigs
+ );
- return of(decodedIdToken);
+ return of(_decodedIdToken);
}
const { renewUserInfoAfterTokenRenew } = currentConfiguration;
if (!isRenewProcess || renewUserInfoAfterTokenRenew || !haveUserData) {
return this.getUserDataOidcFlowAndSave(
- decodedIdToken.sub,
+ _decodedIdToken.sub,
currentConfiguration,
allConfigs
).pipe(
@@ -93,7 +97,7 @@ export class UserService {
'Received user data: ',
userData
);
- if (!!userData) {
+ if (userData) {
this.loggerService.logDebug(
currentConfiguration,
'accessToken: ',
@@ -101,11 +105,10 @@ export class UserService {
);
return of(userData);
- } else {
- return throwError(
- () => new Error('Received no user data, request failed')
- );
}
+ return throwError(
+ () => new Error('Received no user data, request failed')
+ );
})
);
}
@@ -178,16 +181,15 @@ export class UserService {
this.setUserDataToStore(data, currentConfiguration, allConfigs);
return data;
- } else {
- // something went wrong, user data sub does not match that from id_token
- this.loggerService.logWarning(
- currentConfiguration,
- `User data sub does not match sub in id_token, resetting`
- );
- this.resetUserDataInStore(currentConfiguration, allConfigs);
-
- return null;
}
+ // something went wrong, user data sub does not match that from id_token
+ this.loggerService.logWarning(
+ currentConfiguration,
+ 'User data sub does not match sub in id_token, resetting'
+ );
+ this.resetUserDataInStore(currentConfiguration, allConfigs);
+
+ return null;
})
);
}
diff --git a/src/utils/crypto/crypto.service.spec.ts b/src/utils/crypto/crypto.service.spec.ts
index 42f91e5..5f1f6cb 100644
--- a/src/utils/crypto/crypto.service.spec.ts
+++ b/src/utils/crypto/crypto.service.spec.ts
@@ -1,5 +1,6 @@
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DOCUMENT } from '../../dom';
-import { TestBed } from '@angular/core/testing';
import { CryptoService } from './crypto.service';
describe('CryptoService', () => {
diff --git a/src/utils/equality/equality.service.spec.ts b/src/utils/equality/equality.service.spec.ts
index 98f18f7..a074c9b 100644
--- a/src/utils/equality/equality.service.spec.ts
+++ b/src/utils/equality/equality.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { IFrameService } from '../../iframe/existing-iframe.service';
import { EqualityService } from './equality.service';
diff --git a/src/utils/flowHelper/flow-helper.service.spec.ts b/src/utils/flowHelper/flow-helper.service.spec.ts
index 52849ab..b294924 100644
--- a/src/utils/flowHelper/flow-helper.service.spec.ts
+++ b/src/utils/flowHelper/flow-helper.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { FlowHelper } from './flow-helper.service';
describe('Flow Helper Service', () => {
@@ -21,25 +22,25 @@ describe('Flow Helper Service', () => {
it('isCurrentFlowCodeFlow returns false if current flow is not code flow', () => {
const config = { responseType: 'id_token token', configId: 'configId1' };
- expect(flowHelper.isCurrentFlowCodeFlow(config)).toBeFalse();
+ expect(flowHelper.isCurrentFlowCodeFlow(config)).toBeFalsy();
});
it('isCurrentFlowCodeFlow returns true if current flow is code flow', () => {
const config = { responseType: 'code' };
- expect(flowHelper.isCurrentFlowCodeFlow(config)).toBeTrue();
+ expect(flowHelper.isCurrentFlowCodeFlow(config)).toBeTruthy();
});
it('currentFlowIs returns true if current flow is code flow', () => {
const config = { responseType: 'code' };
- expect(flowHelper.currentFlowIs('code', config)).toBeTrue();
+ expect(flowHelper.currentFlowIs('code', config)).toBeTruthy();
});
it('currentFlowIs returns true if current flow is code flow (array)', () => {
const config = { responseType: 'code' };
- expect(flowHelper.currentFlowIs(['code'], config)).toBeTrue();
+ expect(flowHelper.currentFlowIs(['code'], config)).toBeTruthy();
});
it('currentFlowIs returns true if current flow is id_token token or code (array)', () => {
@@ -47,13 +48,13 @@ describe('Flow Helper Service', () => {
expect(
flowHelper.currentFlowIs(['id_token token', 'code'], config)
- ).toBeTrue();
+ ).toBeTruthy();
});
it('currentFlowIs returns true if current flow is code flow', () => {
const config = { responseType: 'id_token token' };
- expect(flowHelper.currentFlowIs('code', config)).toBeFalse();
+ expect(flowHelper.currentFlowIs('code', config)).toBeFalsy();
});
it('isCurrentFlowImplicitFlowWithAccessToken return true if flow is "id_token token"', () => {
@@ -61,7 +62,7 @@ describe('Flow Helper Service', () => {
const result = flowHelper.isCurrentFlowImplicitFlowWithAccessToken(config);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('isCurrentFlowImplicitFlowWithAccessToken return false if flow is not "id_token token"', () => {
@@ -69,7 +70,7 @@ describe('Flow Helper Service', () => {
const result = flowHelper.isCurrentFlowImplicitFlowWithAccessToken(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isCurrentFlowImplicitFlowWithoutAccessToken return true if flow is "id_token"', () => {
@@ -79,7 +80,7 @@ describe('Flow Helper Service', () => {
flowHelper as any
).isCurrentFlowImplicitFlowWithoutAccessToken(config);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('isCurrentFlowImplicitFlowWithoutAccessToken return false if flow is not "id_token token"', () => {
@@ -89,7 +90,7 @@ describe('Flow Helper Service', () => {
flowHelper as any
).isCurrentFlowImplicitFlowWithoutAccessToken(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isCurrentFlowCodeFlowWithRefreshTokens return false if flow is not code flow', () => {
@@ -97,7 +98,7 @@ describe('Flow Helper Service', () => {
const result = flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isCurrentFlowCodeFlowWithRefreshTokens return false if useRefreshToken is set to false', () => {
@@ -105,7 +106,7 @@ describe('Flow Helper Service', () => {
const result = flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config);
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
it('isCurrentFlowCodeFlowWithRefreshTokens return true if useRefreshToken is set to true and code flow', () => {
@@ -113,59 +114,59 @@ describe('Flow Helper Service', () => {
const result = flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config);
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
describe('isCurrentFlowAnyImplicitFlow', () => {
it('returns true if currentFlowIsImplicitFlowWithAccessToken is true', () => {
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
flowHelper as any,
'isCurrentFlowImplicitFlowWithoutAccessToken'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = flowHelper.isCurrentFlowAnyImplicitFlow({
configId: 'configId1',
});
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('returns true if isCurrentFlowImplicitFlowWithoutAccessToken is true', () => {
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
flowHelper as any,
'isCurrentFlowImplicitFlowWithoutAccessToken'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
const result = flowHelper.isCurrentFlowAnyImplicitFlow({
configId: 'configId1',
});
- expect(result).toBeTrue();
+ expect(result).toBeTruthy();
});
it('returns false it is not any implicit flow', () => {
- spyOn(
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(false);
- spyOn(
+ ).mockReturnValue(false);
+ vi.spyOn(
flowHelper as any,
'isCurrentFlowImplicitFlowWithoutAccessToken'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const result = flowHelper.isCurrentFlowAnyImplicitFlow({
configId: 'configId1',
});
- expect(result).toBeFalse();
+ expect(result).toBeFalsy();
});
});
});
diff --git a/src/utils/flowHelper/flow-helper.service.ts b/src/utils/flowHelper/flow-helper.service.ts
index f9454b4..91075c1 100644
--- a/src/utils/flowHelper/flow-helper.service.ts
+++ b/src/utils/flowHelper/flow-helper.service.ts
@@ -1,5 +1,5 @@
import { Injectable } from 'injection-js';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
@Injectable()
export class FlowHelper {
diff --git a/src/utils/platform-provider/platform-provider.spec.ts b/src/utils/platform-provider/platform-provider.spec.ts
index 979a91c..1ad3fea 100644
--- a/src/utils/platform-provider/platform-provider.spec.ts
+++ b/src/utils/platform-provider/platform-provider.spec.ts
@@ -1,5 +1,6 @@
+import { TestBed } from '@/testing';
import { PLATFORM_ID } from '@angular/core';
-import { TestBed } from '@angular/core/testing';
+import { vi } from 'vitest';
import { PlatformProvider } from './platform.provider';
describe('PlatformProvider Tests', () => {
diff --git a/src/utils/redirect/redirect.service.spec.ts b/src/utils/redirect/redirect.service.spec.ts
index 786e5ad..ed498c7 100644
--- a/src/utils/redirect/redirect.service.spec.ts
+++ b/src/utils/redirect/redirect.service.spec.ts
@@ -1,5 +1,6 @@
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DOCUMENT } from '../../dom';
-import { TestBed } from '@angular/core/testing';
import { RedirectService } from './redirect.service';
describe('Redirect Service Tests', () => {
@@ -38,9 +39,9 @@ describe('Redirect Service Tests', () => {
});
it('redirectTo sets window location href', () => {
- const spy = spyOnProperty(myDocument.location, 'href', 'set');
+ const spy = vi.spyOnProperty(myDocument.location, 'href', 'set');
service.redirectTo('anyurl');
- expect(spy).toHaveBeenCalledOnceWith('anyurl');
+ expect(spy).toHaveBeenCalledExactlyOnceWith('anyurl');
});
});
diff --git a/src/utils/tokenHelper/token-helper.service.spec.ts b/src/utils/tokenHelper/token-helper.service.spec.ts
index d3ee296..437aff5 100644
--- a/src/utils/tokenHelper/token-helper.service.spec.ts
+++ b/src/utils/tokenHelper/token-helper.service.spec.ts
@@ -1,6 +1,7 @@
-import { TestBed } from '@angular/core/testing';
-import { mockProvider } from '../../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { LoggerService } from '../../logging/logger.service';
+import { mockProvider } from '../../testing/mock';
import { TokenHelperService } from './token-helper.service';
describe('Token Helper Service', () => {
diff --git a/src/utils/url/current-url.service.spec.ts b/src/utils/url/current-url.service.spec.ts
index cd05d81..3a9d21b 100644
--- a/src/utils/url/current-url.service.spec.ts
+++ b/src/utils/url/current-url.service.spec.ts
@@ -1,5 +1,6 @@
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { DOCUMENT } from '../../dom';
-import { TestBed } from '@angular/core/testing';
import { CurrentUrlService } from './current-url.service';
describe('CurrentUrlService with existing Url', () => {
@@ -36,7 +37,7 @@ describe('CurrentUrlService with existing Url', () => {
describe('getStateParamFromCurrentUrl', () => {
it('returns null if there is no current URL', () => {
- spyOn(service, 'getCurrentUrl').and.returnValue(null);
+ vi.spyOn(service, 'getCurrentUrl').mockReturnValue(null);
const stateParam = service.getStateParamFromCurrentUrl('');
diff --git a/src/utils/url/url.service.spec.ts b/src/utils/url/url.service.spec.ts
index 09ba88f..0100a71 100644
--- a/src/utils/url/url.service.spec.ts
+++ b/src/utils/url/url.service.spec.ts
@@ -1,10 +1,11 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../../test/auto-mock';
-import { OpenIdConfiguration } from '../../config/openid-configuration';
+import { vi } from 'vitest';
+import type { OpenIdConfiguration } from '../../config/openid-configuration';
import { FlowsDataService } from '../../flows/flows-data.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
+import { mockProvider } from '../../testing/mock';
import { JwtWindowCryptoService } from '../../validation/jwt-window-crypto.service';
import { FlowHelper } from '../flowHelper/flow-helper.service';
import { UrlService } from './url.service';
@@ -59,7 +60,7 @@ describe('UrlService Tests', () => {
const sut = service.getUrlWithoutQueryParameters(url);
params.forEach((p) => {
- expect(sut.searchParams.has(p.key)).toBeFalse();
+ expect(sut.searchParams.has(p.key)).toBeFalsy();
});
});
});
@@ -90,7 +91,7 @@ describe('UrlService Tests', () => {
it(`should return true for ${mu.toString()}`, () => {
expect(
service.queryParametersExist(expected, mu.searchParams)
- ).toBeTrue();
+ ).toBeTruthy();
});
});
@@ -98,7 +99,7 @@ describe('UrlService Tests', () => {
it(`should return false for ${nmu.toString()}`, () => {
expect(
service.queryParametersExist(expected, nmu.searchParams)
- ).toBeFalse();
+ ).toBeFalsy();
});
});
});
@@ -130,7 +131,7 @@ describe('UrlService Tests', () => {
];
nonMatchingUrls.forEach((nmu) => {
- expect(service.isCallbackFromSts(nmu.url, nmu.config)).toBeFalse();
+ expect(service.isCallbackFromSts(nmu.url, nmu.config)).toBeFalsy();
});
});
@@ -271,9 +272,11 @@ describe('UrlService Tests', () => {
const config = { configId: 'configId1', clientId: '' };
const authorizationEndpoint = 'authorizationEndpoint';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -294,9 +297,11 @@ describe('UrlService Tests', () => {
};
const authorizationEndpoint = 'authorizationEndpoint';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -318,9 +323,11 @@ describe('UrlService Tests', () => {
};
const authorizationEndpoint = 'authorizationEndpoint';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -347,9 +354,11 @@ describe('UrlService Tests', () => {
testcustom: 'customvalue',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint: 'http://example' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint: 'http://example' })
+ );
const value = (service as any).createAuthorizeUrl(
'codeChallenge', // Code Flow
@@ -384,11 +393,13 @@ describe('UrlService Tests', () => {
config.scope = 'openid email profile';
config.configId = 'configId1';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -423,11 +434,13 @@ describe('UrlService Tests', () => {
config.scope = 'openid email profile';
config.configId = 'configId1';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -465,11 +478,13 @@ describe('UrlService Tests', () => {
config.hdParam = 'myHdParam';
config.configId = 'configId1';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -507,11 +522,13 @@ describe('UrlService Tests', () => {
testcustom: 'customvalue',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -552,11 +569,13 @@ describe('UrlService Tests', () => {
t1: ';,/?:@&=+$',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -594,11 +613,13 @@ describe('UrlService Tests', () => {
},
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -635,11 +656,13 @@ describe('UrlService Tests', () => {
configId: 'configId1',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -674,11 +697,13 @@ describe('UrlService Tests', () => {
configId: 'configId1',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -713,12 +738,14 @@ describe('UrlService Tests', () => {
config.responseType = 'id_token token';
config.scope = 'openid email profile';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint:
'https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_sign_in',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -752,11 +779,13 @@ describe('UrlService Tests', () => {
config.scope = 'openid email profile';
config.configId = 'configId1';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'http://example',
- });
+ })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -792,9 +821,11 @@ describe('UrlService Tests', () => {
prompt: 'select_account',
};
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint: 'http://example' });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint: 'http://example' })
+ );
const value = (service as any).createAuthorizeUrl(
'', // Implicit Flow
@@ -835,11 +866,13 @@ describe('UrlService Tests', () => {
const revocationEndpoint = 'http://example?cod=ddd';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
revocationEndpoint,
- });
+ })
+ );
const value = service.createRevocationEndpointBodyAccessToken(
'mytoken',
@@ -880,11 +913,13 @@ describe('UrlService Tests', () => {
const revocationEndpoint = 'http://example?cod=ddd';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
revocationEndpoint,
- });
+ })
+ );
const value = service.createRevocationEndpointBodyRefreshToken(
'mytoken',
@@ -925,11 +960,13 @@ describe('UrlService Tests', () => {
const revocationEndpoint = 'http://example?cod=ddd';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
revocationEndpoint,
- });
+ })
+ );
const value = service.getRevocationEndpointUrl(config);
@@ -952,11 +989,13 @@ describe('UrlService Tests', () => {
const revocationEndpoint = 'http://example';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
revocationEndpoint,
- });
+ })
+ );
const value = service.getRevocationEndpointUrl(config);
@@ -966,11 +1005,13 @@ describe('UrlService Tests', () => {
});
it('getRevocationEndpointUrl returns null when there is not revociationendpoint given', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', {})
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', {}],
+ () => ({
revocationEndpoint: null,
- });
+ })
+ );
const value = service.getRevocationEndpointUrl({});
expect(value).toBeNull();
@@ -1002,22 +1043,22 @@ describe('UrlService Tests', () => {
});
describe('getAuthorizeUrl', () => {
- it('returns null if no config is given', waitForAsync(() => {
+ it('returns null if no config is given', async () => {
service.getAuthorizeUrl(null).subscribe((url) => {
expect(url).toBeNull();
});
- }));
+ });
- it('returns null if current flow is code flow and no redirect url is defined', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
+ it('returns null if current flow is code flow and no redirect url is defined', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
service.getAuthorizeUrl({ configId: 'configId1' }).subscribe((result) => {
expect(result).toBeNull();
});
- }));
+ });
- it('returns empty string if current flow is code flow, config disabled pkce and there is a redirecturl', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
+ it('returns empty string if current flow is code flow, config disabled pkce and there is a redirecturl', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
const config = {
configId: 'configId1',
disablePkce: true,
@@ -1027,10 +1068,10 @@ describe('UrlService Tests', () => {
service.getAuthorizeUrl(config).subscribe((result) => {
expect(result).toBe('');
});
- }));
+ });
- it('returns url if current flow is code flow, config disabled pkce, there is a redirecturl and awkep are given', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
+ it('returns url if current flow is code flow, config disabled pkce, there is a redirecturl and awkep are given', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
const config = {
configId: 'configId1',
disablePkce: false,
@@ -1044,27 +1085,29 @@ describe('UrlService Tests', () => {
const authorizationEndpoint = 'authorizationEndpoint';
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of('some-code-challenge')
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
service.getAuthorizeUrl(config).subscribe((result) => {
expect(result).toBe(
'authorizationEndpoint?client_id=some-clientId&redirect_uri=some-redirectUrl&response_type=testResponseType&scope=testScope&nonce=undefined&state=undefined&code_challenge=some-code-challenge&code_challenge_method=S256'
);
});
- }));
+ });
- it('calls createUrlImplicitFlowAuthorize if current flow is NOT code flow', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- const spyCreateUrlCodeFlowAuthorize = spyOn(
+ it('calls createUrlImplicitFlowAuthorize if current flow is NOT code flow', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ const spyCreateUrlCodeFlowAuthorize = vi.spyOn(
service as any,
'createUrlCodeFlowAuthorize'
);
- const spyCreateUrlImplicitFlowAuthorize = spyOn(
+ const spyCreateUrlImplicitFlowAuthorize = vi.spyOn(
service as any,
'createUrlImplicitFlowAuthorize'
);
@@ -1073,39 +1116,38 @@ describe('UrlService Tests', () => {
expect(spyCreateUrlCodeFlowAuthorize).not.toHaveBeenCalled();
expect(spyCreateUrlImplicitFlowAuthorize).toHaveBeenCalled();
});
- }));
+ });
- it('return empty string if flow is not code flow and createUrlImplicitFlowAuthorize returns falsy', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- const spy = spyOn(
- service as any,
- 'createUrlImplicitFlowAuthorize'
- ).and.returnValue('');
+ it('return empty string if flow is not code flow and createUrlImplicitFlowAuthorize returns falsy', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ const spy = vi
+ .spyOn(service as any, 'createUrlImplicitFlowAuthorize')
+ .mockReturnValue('');
const resultObs$ = service.getAuthorizeUrl({ configId: 'configId1' });
resultObs$.subscribe((result) => {
expect(spy).toHaveBeenCalled();
expect(result).toBe('');
});
- }));
+ });
});
describe('getRefreshSessionSilentRenewUrl', () => {
it('calls createUrlCodeFlowWithSilentRenew if current flow is code flow', () => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
- const spy = spyOn(service as any, 'createUrlCodeFlowWithSilentRenew');
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
+ const spy = vi.spyOn(service as any, 'createUrlCodeFlowWithSilentRenew');
service.getRefreshSessionSilentRenewUrl({ configId: 'configId1' });
expect(spy).toHaveBeenCalled();
});
it('calls createUrlImplicitFlowWithSilentRenew if current flow is NOT code flow', () => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- const spyCreateUrlCodeFlowWithSilentRenew = spyOn(
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ const spyCreateUrlCodeFlowWithSilentRenew = vi.spyOn(
service as any,
'createUrlCodeFlowWithSilentRenew'
);
- const spyCreateUrlImplicitFlowWithSilentRenew = spyOn(
+ const spyCreateUrlImplicitFlowWithSilentRenew = vi.spyOn(
service as any,
'createUrlImplicitFlowWithSilentRenew'
);
@@ -1115,12 +1157,11 @@ describe('UrlService Tests', () => {
expect(spyCreateUrlImplicitFlowWithSilentRenew).toHaveBeenCalled();
});
- it('return empty string if flow is not code flow and createUrlImplicitFlowWithSilentRenew returns falsy', waitForAsync(() => {
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
- const spy = spyOn(
- service as any,
- 'createUrlImplicitFlowWithSilentRenew'
- ).and.returnValue('');
+ it('return empty string if flow is not code flow and createUrlImplicitFlowWithSilentRenew returns falsy', async () => {
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
+ const spy = vi
+ .spyOn(service as any, 'createUrlImplicitFlowWithSilentRenew')
+ .mockReturnValue('');
const resultObs$ = service.getRefreshSessionSilentRenewUrl({
configId: 'configId1',
});
@@ -1129,12 +1170,12 @@ describe('UrlService Tests', () => {
expect(spy).toHaveBeenCalled();
expect(result).toBe('');
});
- }));
+ });
});
describe('createBodyForCodeFlowCodeRequest', () => {
it('returns null if no code verifier is set', () => {
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(null);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(null);
const result = service.createBodyForCodeFlowCodeRequest(
'notRelevantParam',
{ configId: 'configId1' }
@@ -1146,7 +1187,9 @@ describe('UrlService Tests', () => {
it('returns null if no clientId is set', () => {
const codeVerifier = 'codeverifier';
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(codeVerifier);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(
+ codeVerifier
+ );
const clientId = '';
const result = service.createBodyForCodeFlowCodeRequest(
'notRelevantParam',
@@ -1162,8 +1205,10 @@ describe('UrlService Tests', () => {
const redirectUrl = '';
const clientId = 'clientId';
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(codeVerifier);
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(
+ codeVerifier
+ );
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
const result = service.createBodyForCodeFlowCodeRequest(code, {
clientId,
@@ -1179,8 +1224,10 @@ describe('UrlService Tests', () => {
const redirectUrl = 'redirectUrl';
const clientId = 'clientId';
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(codeVerifier);
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(
+ codeVerifier
+ );
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
const result = service.createBodyForCodeFlowCodeRequest(code, {
clientId,
@@ -1197,8 +1244,10 @@ describe('UrlService Tests', () => {
const silentRenewUrl = 'silentRenewUrl';
const clientId = 'clientId';
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(codeVerifier);
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(
+ codeVerifier
+ );
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
const result = service.createBodyForCodeFlowCodeRequest(code, {
clientId,
@@ -1216,8 +1265,10 @@ describe('UrlService Tests', () => {
const clientId = 'clientId';
const customTokenParams = { foo: 'bar' };
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(codeVerifier);
- spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(
+ codeVerifier
+ );
+ vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
const result = service.createBodyForCodeFlowCodeRequest(
code,
@@ -1237,9 +1288,9 @@ describe('UrlService Tests', () => {
disablePkce: false,
};
- spyOn(flowsDataService, 'getCodeVerifier').and.returnValue(null);
+ vi.spyOn(flowsDataService, 'getCodeVerifier').mockReturnValue(null);
- const loggerspy = spyOn(loggerService, 'logError');
+ const loggerspy = vi.spyOn(loggerService, 'logError');
const result = service.createBodyForCodeFlowCodeRequest(
code,
config,
@@ -1247,7 +1298,7 @@ describe('UrlService Tests', () => {
);
expect(result).toBe(null);
- expect(loggerspy).toHaveBeenCalledOnceWith(
+ expect(loggerspy).toHaveBeenCalledExactlyOnceWith(
config,
'CodeVerifier is not set ',
null
@@ -1296,7 +1347,7 @@ describe('UrlService Tests', () => {
});
describe('createBodyForParCodeFlowRequest', () => {
- it('returns null redirectUrl is falsy', waitForAsync(() => {
+ it('returns null redirectUrl is falsy', async () => {
const resultObs$ = service.createBodyForParCodeFlowRequest({
redirectUrl: '',
});
@@ -1304,9 +1355,9 @@ describe('UrlService Tests', () => {
resultObs$.subscribe((result) => {
expect(result).toBe(null);
});
- }));
+ });
- it('returns basic URL with no extras if properties are given', waitForAsync(() => {
+ it('returns basic URL with no extras if properties are given', async () => {
const config = {
clientId: 'testClientId',
responseType: 'testResponseType',
@@ -1316,15 +1367,15 @@ describe('UrlService Tests', () => {
redirectUrl: 'testRedirectUrl',
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('testState');
- spyOn(flowsDataService, 'createNonce').and.returnValue('testNonce');
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue('testState');
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue('testNonce');
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
'testCodeVerifier'
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of('testCodeChallenge')
);
@@ -1335,9 +1386,9 @@ describe('UrlService Tests', () => {
`client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256`
);
});
- }));
+ });
- it('returns basic URL with hdParam if properties are given', waitForAsync(() => {
+ it('returns basic URL with hdParam if properties are given', async () => {
const config = {
clientId: 'testClientId',
responseType: 'testResponseType',
@@ -1347,15 +1398,15 @@ describe('UrlService Tests', () => {
redirectUrl: 'testRedirectUrl',
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('testState');
- spyOn(flowsDataService, 'createNonce').and.returnValue('testNonce');
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue('testState');
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue('testNonce');
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
'testCodeVerifier'
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of('testCodeChallenge')
);
@@ -1366,9 +1417,9 @@ describe('UrlService Tests', () => {
`client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam`
);
});
- }));
+ });
- it('returns basic URL with hdParam and custom params if properties are given', waitForAsync(() => {
+ it('returns basic URL with hdParam and custom params if properties are given', async () => {
const config = {
clientId: 'testClientId',
responseType: 'testResponseType',
@@ -1378,15 +1429,15 @@ describe('UrlService Tests', () => {
redirectUrl: 'testRedirectUrl',
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('testState');
- spyOn(flowsDataService, 'createNonce').and.returnValue('testNonce');
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue('testState');
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue('testNonce');
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
'testCodeVerifier'
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of('testCodeChallenge')
);
@@ -1397,9 +1448,9 @@ describe('UrlService Tests', () => {
`client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing`
);
});
- }));
+ });
- it('returns basic URL with hdParam and custom params and passed cutom params if properties are given', waitForAsync(() => {
+ it('returns basic URL with hdParam and custom params and passed cutom params if properties are given', async () => {
const config = {
clientId: 'testClientId',
responseType: 'testResponseType',
@@ -1409,15 +1460,15 @@ describe('UrlService Tests', () => {
redirectUrl: 'testRedirectUrl',
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue('testState');
- spyOn(flowsDataService, 'createNonce').and.returnValue('testNonce');
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue('testState');
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue('testNonce');
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
'testCodeVerifier'
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of('testCodeChallenge')
);
@@ -1432,7 +1483,7 @@ describe('UrlService Tests', () => {
`client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing&any=otherThing`
);
});
- }));
+ });
});
describe('createUrlImplicitFlowWithSilentRenew', () => {
@@ -1441,11 +1492,11 @@ describe('UrlService Tests', () => {
const nonce = 'testNonce';
const silentRenewUrl = null;
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
const config = {
silentRenewUrl,
@@ -1473,17 +1524,19 @@ describe('UrlService Tests', () => {
scope,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint,
- });
+ })
+ );
const serviceAsAny = service as any;
@@ -1506,15 +1559,17 @@ describe('UrlService Tests', () => {
responseType,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
const serviceAsAny = service as any;
@@ -1525,22 +1580,22 @@ describe('UrlService Tests', () => {
});
describe('createUrlCodeFlowWithSilentRenew', () => {
- it('returns empty string if silentrenewUrl is falsy', waitForAsync(() => {
+ it('returns empty string if silentrenewUrl is falsy', async () => {
const state = 'testState';
const nonce = 'testNonce';
const silentRenewUrl = null;
const codeVerifier = 'codeVerifier';
const codeChallenge = 'codeChallenge ';
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
@@ -1555,9 +1610,9 @@ describe('UrlService Tests', () => {
resultObs$.subscribe((result: any) => {
expect(result).toBe('');
});
- }));
+ });
- it('returns correct URL if wellknownendpoints are given', waitForAsync(() => {
+ it('returns correct URL if wellknownendpoints are given', async () => {
const state = 'testState';
const nonce = 'testNonce';
const silentRenewUrl = 'http://any-url.com';
@@ -1574,21 +1629,23 @@ describe('UrlService Tests', () => {
scope,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const serviceAsAny = service as any;
@@ -1599,9 +1656,9 @@ describe('UrlService Tests', () => {
`authorizationEndpoint?client_id=${clientId}&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&prompt=none`
);
});
- }));
+ });
- it('returns empty string if no wellknownendpoints are given', waitForAsync(() => {
+ it('returns empty string if no wellknownendpoints are given', async () => {
const state = 'testState';
const nonce = 'testNonce';
const silentRenewUrl = 'http://any-url.com';
@@ -1615,20 +1672,22 @@ describe('UrlService Tests', () => {
responseType,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
const serviceAsAny = service as any;
@@ -1637,7 +1696,7 @@ describe('UrlService Tests', () => {
resultObs$.subscribe((result: any) => {
expect(result).toBe('');
});
- }));
+ });
});
describe('createUrlImplicitFlowAuthorize', () => {
@@ -1656,15 +1715,17 @@ describe('UrlService Tests', () => {
scope,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const serviceAsAny = service as any;
@@ -1683,15 +1744,17 @@ describe('UrlService Tests', () => {
const responseType = 'responseType';
const config = { redirectUrl, clientId, responseType };
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
const serviceAsAny = service as any;
@@ -1708,14 +1771,16 @@ describe('UrlService Tests', () => {
const responseType = 'responseType';
const config = { redirectUrl, clientId, responseType };
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
const serviceAsAny = service as any;
@@ -1726,7 +1791,7 @@ describe('UrlService Tests', () => {
});
describe('createUrlCodeFlowAuthorize', () => {
- it('returns null if redirectUrl is falsy', waitForAsync(() => {
+ it('returns null if redirectUrl is falsy', async () => {
const state = 'testState';
const nonce = 'testNonce';
const redirectUrl = null;
@@ -1734,11 +1799,11 @@ describe('UrlService Tests', () => {
redirectUrl,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
const serviceAsAny = service as any;
@@ -1747,9 +1812,9 @@ describe('UrlService Tests', () => {
resultObs$.subscribe((result: any) => {
expect(result).toBeNull();
});
- }));
+ });
- it('returns correct URL if wellknownendpoints are given', waitForAsync(() => {
+ it('returns correct URL if wellknownendpoints are given', async () => {
const state = 'testState';
const nonce = 'testNonce';
const scope = 'testScope';
@@ -1766,20 +1831,22 @@ describe('UrlService Tests', () => {
scope,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const serviceAsAny = service as any;
@@ -1790,9 +1857,9 @@ describe('UrlService Tests', () => {
`authorizationEndpoint?client_id=clientId&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}`
);
});
- }));
+ });
- it('returns correct URL if wellknownendpoints and custom params are given', waitForAsync(() => {
+ it('returns correct URL if wellknownendpoints and custom params are given', async () => {
const state = 'testState';
const nonce = 'testNonce';
const scope = 'testScope';
@@ -1811,21 +1878,23 @@ describe('UrlService Tests', () => {
configId,
};
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({ authorizationEndpoint });
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({ authorizationEndpoint })
+ );
const serviceAsAny = service as any;
@@ -1839,9 +1908,9 @@ describe('UrlService Tests', () => {
`&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&to=add&as=well`
);
});
- }));
+ });
- it('returns empty string if no wellknownendpoints are given', waitForAsync(() => {
+ it('returns empty string if no wellknownendpoints are given', async () => {
const state = 'testState';
const nonce = 'testNonce';
const redirectUrl = 'http://any-url.com';
@@ -1851,20 +1920,22 @@ describe('UrlService Tests', () => {
const codeChallenge = 'codeChallenge ';
const config = { redirectUrl, clientId, responseType };
- spyOn(
+ vi.spyOn(
flowsDataService,
'getExistingOrCreateAuthStateControl'
- ).and.returnValue(state);
- spyOn(flowsDataService, 'createNonce').and.returnValue(nonce);
- spyOn(flowsDataService, 'createCodeVerifier').and.returnValue(
+ ).mockReturnValue(state);
+ vi.spyOn(flowsDataService, 'createNonce').mockReturnValue(nonce);
+ vi.spyOn(flowsDataService, 'createCodeVerifier').mockReturnValue(
codeVerifier
);
- spyOn(jwtWindowCryptoService, 'generateCodeChallenge').and.returnValue(
+ vi.spyOn(jwtWindowCryptoService, 'generateCodeChallenge').mockReturnValue(
of(codeChallenge)
);
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => null
+ );
const serviceAsAny = service as any;
@@ -1873,7 +1944,7 @@ describe('UrlService Tests', () => {
resultObs$.subscribe((result: any) => {
expect(result).toBe('');
});
- }));
+ });
});
describe('getEndSessionUrl', () => {
@@ -1889,12 +1960,16 @@ describe('UrlService Tests', () => {
postLogoutRedirectUri: 'https://localhost:44386/Unauthorized',
} as OpenIdConfiguration;
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('mytoken');
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
+ 'mytoken'
+ );
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
endSessionEndpoint: 'http://example',
- });
+ })
+ );
// Act
const value = service.getEndSessionUrl(config);
@@ -1912,12 +1987,14 @@ describe('UrlService Tests', () => {
postLogoutRedirectUri: 'https://localhost:44386/Unauthorized',
} as OpenIdConfiguration;
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
endSessionEndpoint: 'http://example',
- });
+ })
+ );
// Act
const value = service.getEndSessionUrl(config);
@@ -1935,12 +2012,16 @@ describe('UrlService Tests', () => {
postLogoutRedirectUri: 'https://localhost:44386/Unauthorized',
} as OpenIdConfiguration;
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('mytoken');
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
+ 'mytoken'
+ );
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
endSessionEndpoint: 'http://example',
- });
+ })
+ );
// Act
const value = service.getEndSessionUrl(config, { param: 'to-add' });
@@ -1960,12 +2041,14 @@ describe('UrlService Tests', () => {
const endSessionEndpoint =
'https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/logout?p=b2c_1_sign_in';
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
endSessionEndpoint,
- });
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
+ })
+ );
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
'UzI1NiIsImtpZCI6Il'
);
@@ -1986,12 +2069,16 @@ describe('UrlService Tests', () => {
postLogoutRedirectUri: '',
} as OpenIdConfiguration;
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
endSessionEndpoint: 'http://example',
- });
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('mytoken');
+ })
+ );
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
+ 'mytoken'
+ );
// Act
const value = service.getEndSessionUrl(config);
@@ -2004,12 +2091,16 @@ describe('UrlService Tests', () => {
it('returns null if no wellknownEndpoints.endSessionEndpoint given', () => {
// Arrange
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', {})
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', {}],
+ () => ({
endSessionEndpoint: null,
- });
- spyOn(storagePersistenceService, 'getIdToken').and.returnValue('mytoken');
+ })
+ );
+ vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
+ 'mytoken'
+ );
// Act
const value = service.getEndSessionUrl({});
@@ -2038,9 +2129,11 @@ describe('UrlService Tests', () => {
describe('getAuthorizeParUrl', () => {
it('returns null if authWellKnownEndPoints is undefined', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue(null);
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => null
+ );
const result = service.getAuthorizeParUrl('', { configId: 'configId1' });
@@ -2048,11 +2141,13 @@ describe('UrlService Tests', () => {
});
it('returns null if authWellKnownEndPoints-authorizationEndpoint is undefined', () => {
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', { configId: 'configId1' })
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', { configId: 'configId1' }],
+ () => ({
notAuthorizationEndpoint: 'anything',
- });
+ })
+ );
const result = service.getAuthorizeParUrl('', { configId: 'configId1' });
@@ -2062,11 +2157,13 @@ describe('UrlService Tests', () => {
it('returns null if configurationProvider.openIDConfiguration has no clientId', () => {
const config = { clientId: '' } as OpenIdConfiguration;
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'anything',
- });
+ })
+ );
const result = service.getAuthorizeParUrl('', config);
@@ -2076,11 +2173,13 @@ describe('UrlService Tests', () => {
it('returns correct URL when everything is given', () => {
const config = { clientId: 'clientId' };
- spyOn(storagePersistenceService, 'read')
- .withArgs('authWellKnownEndPoints', config)
- .and.returnValue({
+ mockImplementationWhenArgsEqual(
+ vi.spyOn(storagePersistenceService, 'read'),
+ ['authWellKnownEndPoints', config],
+ () => ({
authorizationEndpoint: 'anything',
- });
+ })
+ );
const result = service.getAuthorizeParUrl('passedRequestUri', config);
diff --git a/src/validation/jwk-window-crypto.service.spec.ts b/src/validation/jwk-window-crypto.service.spec.ts
index f2737b9..9aa8489 100644
--- a/src/validation/jwk-window-crypto.service.spec.ts
+++ b/src/validation/jwk-window-crypto.service.spec.ts
@@ -1,5 +1,6 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { base64url } from 'rfc4648';
+import { vi } from 'vitest';
import { CryptoService } from '../utils/crypto/crypto.service';
import { JwkWindowCryptoService } from './jwk-window-crypto.service';
@@ -43,9 +44,9 @@ describe('JwkWindowCryptoService', () => {
});
});
- beforeEach(waitForAsync(() => {
+ beforeEach(async () => {
service = TestBed.inject(JwkWindowCryptoService);
- }));
+ });
it('should create', () => {
expect(service).toBeTruthy();
diff --git a/src/validation/jwt-window-crypto.service.spec.ts b/src/validation/jwt-window-crypto.service.spec.ts
index ecc3f53..ec9eab0 100644
--- a/src/validation/jwt-window-crypto.service.spec.ts
+++ b/src/validation/jwt-window-crypto.service.spec.ts
@@ -1,4 +1,5 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
+import { vi } from 'vitest';
import { CryptoService } from '../utils/crypto/crypto.service';
import { JwtWindowCryptoService } from './jwt-window-crypto.service';
@@ -21,7 +22,7 @@ describe('JwtWindowCryptoService', () => {
});
describe('generateCodeChallenge', () => {
- it('returns good result with correct codeVerifier', waitForAsync(() => {
+ it('returns good result with correct codeVerifier', async () => {
const outcome = 'R2TWD45Vtcf_kfAqjuE3LMSRF3JDE5fsFndnn6-a0nQ';
const observable = service.generateCodeChallenge(
'44445543344242132145455aaabbdc3b4'
@@ -30,6 +31,6 @@ describe('JwtWindowCryptoService', () => {
observable.subscribe((value) => {
expect(value).toBe(outcome);
});
- }));
+ });
});
});
diff --git a/src/validation/state-validation.service.spec.ts b/src/validation/state-validation.service.spec.ts
index 3314271..32e9e4f 100644
--- a/src/validation/state-validation.service.spec.ts
+++ b/src/validation/state-validation.service.spec.ts
@@ -1,12 +1,13 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
+import { TestBed } from '@/testing';
import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
-import { AuthWellKnownEndpoints } from '../config/auth-well-known/auth-well-known-endpoints';
-import { OpenIdConfiguration } from '../config/openid-configuration';
-import { CallbackContext } from '../flows/callback-context';
+import { vi } from 'vitest';
+import type { AuthWellKnownEndpoints } from '../config/auth-well-known/auth-well-known-endpoints';
+import type { OpenIdConfiguration } from '../config/openid-configuration';
+import type { CallbackContext } from '../flows/callback-context';
import { LogLevel } from '../logging/log-level';
import { LoggerService } from '../logging/logger.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
+import { mockProvider } from '../testing/mock';
import { EqualityService } from '../utils/equality/equality.service';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
@@ -112,10 +113,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -187,10 +188,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -262,10 +263,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -337,10 +338,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -412,10 +413,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -487,10 +488,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -562,10 +563,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -637,10 +638,10 @@ describe('State Validation Service', () => {
triggerRefreshWhenIdTokenExpired: true,
};
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -686,7 +687,7 @@ describe('State Validation Service', () => {
});
describe('getValidatedStateResult', () => {
- it('should return authResponseIsValid false when null is passed', waitForAsync(() => {
+ it('should return authResponseIsValid false when null is passed', async () => {
const isValidObs$ = stateValidationService.getValidatedStateResult(
{} as CallbackContext,
config
@@ -695,18 +696,18 @@ describe('State Validation Service', () => {
isValidObs$.subscribe((isValid) => {
expect(isValid.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid context error', waitForAsync(() => {
- spyOn(
+ it('should return invalid context error', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
false
);
@@ -732,70 +733,79 @@ describe('State Validation Service', () => {
isValidObs$.subscribe((isValid) => {
expect(isValid.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenExpNotExpired is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenExpNotExpired is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.returnValue(false);
- spyOn(
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
+ false
+ );
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- true
- );
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(true)
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
config.clientId = '';
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(false);
- const readSpy = spyOn(storagePersistenceService, 'read');
+ ).mockReturnValue(false);
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -817,7 +827,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback id token expired'
);
@@ -826,25 +836,25 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateStateFromHashCallback is false', waitForAsync(() => {
- const readSpy = spyOn(storagePersistenceService, 'read');
+ it('should return invalid result if validateStateFromHashCallback is false', async () => {
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- spyOn(
+ .mockReturnValue('authStateControl');
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -870,7 +880,7 @@ describe('State Validation Service', () => {
).toHaveBeenCalled();
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect state'
);
@@ -879,48 +889,57 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBeDefined();
expect(state.idToken).toBe('');
});
- }));
+ });
- it('access_token should equal result.access_token and is valid if response_type is "id_token token"', waitForAsync(() => {
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ it('access_token should equal result.access_token and is valid if response_type is "id_token token"', async () => {
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
+ false
);
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.returnValue(false);
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- true
- );
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(true)
);
@@ -929,15 +948,15 @@ describe('State Validation Service', () => {
config.autoCleanStateAfterAuthentication = false;
config.responseType = 'id_token token';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
const callbackContext = {
code: 'fdffsdfsdf',
@@ -964,32 +983,33 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(true);
});
- }));
+ });
- it('should return invalid result if validateSignatureIdToken is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateSignatureIdToken is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(false)
- );
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(false));
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- const logDebugSpy = spyOn(loggerService, 'logDebug').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ const logDebugSpy = vi
+ .spyOn(loggerService, 'logDebug')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1012,7 +1032,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logDebugSpy.calls.allArgs()).toEqual([
+ expect(logDebugSpy).toBeCalledWith([
[config, 'authCallback Signature validation failed id_token'],
[config, 'authCallback token(s) invalid'],
]);
@@ -1022,36 +1042,37 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenNonce is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenNonce is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
false
);
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1073,7 +1094,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect nonce, did you call the checkAuth() method multiple times?'
);
@@ -1082,43 +1103,45 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateRequiredIdToken is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateRequiredIdToken is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- false
- );
- const readSpy = spyOn(storagePersistenceService, 'read');
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(false);
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logDebugSpy = spyOn(loggerService, 'logDebug').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logDebugSpy = vi
+ .spyOn(loggerService, 'logDebug')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1153,46 +1176,48 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenIatMaxOffset is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenIatMaxOffset is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1214,7 +1239,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback Validation, iat rejected id_token was issued too far away from the current time'
);
@@ -1223,53 +1248,55 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenIss is false and has authWellKnownEndPoints', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenIss is false and has authWellKnownEndPoints', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
false
);
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1291,7 +1318,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect iss does not match authWellKnownEndpoints issuer'
);
@@ -1300,41 +1327,43 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenIss is false and has no authWellKnownEndPoints', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenIss is false and has no authWellKnownEndPoints', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
- readSpy.withArgs('authWellKnownEndPoints', config).and.returnValue(null);
+ readSpy.withArgs('authWellKnownEndPoints', config).mockReturnValue(null);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1356,7 +1385,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authWellKnownEndpoints is undefined'
);
@@ -1367,49 +1396,53 @@ describe('State Validation Service', () => {
expect(state.authResponseIsValid).toBe(false);
expect(state.state).toBe(ValidationResult.NoAuthWellKnownEndPoints);
});
- }));
+ });
- it('should return invalid result if validateIdTokenAud is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenAud is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
false
);
config.clientId = '';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1431,7 +1464,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect aud'
);
@@ -1440,51 +1473,57 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return invalid result if validateIdTokenAzpExistsIfMoreThanOneAud is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenAzpExistsIfMoreThanOneAud is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
config.clientId = '';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1506,7 +1545,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback missing azp'
);
@@ -1516,54 +1555,61 @@ describe('State Validation Service', () => {
expect(state.authResponseIsValid).toBe(false);
expect(state.state).toBe(ValidationResult.IncorrectAzp);
});
- }));
+ });
- it('should return invalid result if validateIdTokenAzpValid is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if validateIdTokenAzpValid is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- false
- );
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(false);
config.clientId = '';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1585,7 +1631,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect azp'
);
@@ -1595,58 +1641,65 @@ describe('State Validation Service', () => {
expect(state.authResponseIsValid).toBe(false);
expect(state.state).toBe(ValidationResult.IncorrectAzp);
});
- }));
+ });
- it('should return invalid result if isIdTokenAfterRefreshTokenRequestValid is false', waitForAsync(() => {
- spyOn(
+ it('should return invalid result if isIdTokenAfterRefreshTokenRequestValid is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
- tokenValidationService,
- 'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
true
);
- spyOn(
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpExistsIfMoreThanOneAud'
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
+ vi.spyOn(
stateValidationService as any,
'isIdTokenAfterRefreshTokenRequestValid'
- ).and.returnValue(false);
+ ).mockReturnValue(false);
config.clientId = '';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1668,7 +1721,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback pre, post id_token claims do not match in refresh'
);
@@ -1680,67 +1733,76 @@ describe('State Validation Service', () => {
ValidationResult.IncorrectIdTokenClaimsAfterRefresh
);
});
- }));
+ });
- it('Reponse is valid if authConfiguration.response_type does not equal "id_token token"', waitForAsync(() => {
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.returnValue(false);
- spyOn(
+ it('Reponse is valid if authConfiguration.response_type does not equal "id_token token"', async () => {
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
+ false
+ );
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- true
- );
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(true)
);
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
config.clientId = '';
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'NOT id_token token';
config.autoCleanStateAfterAuthentication = false;
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
- const logDebugSpy = spyOn(loggerService, 'logDebug').and.callFake(
- () => undefined
- );
+ const logDebugSpy = vi
+ .spyOn(loggerService, 'logDebug')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1776,69 +1838,78 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(true);
});
- }));
+ });
- it('Response is invalid if validateIdTokenAtHash is false', waitForAsync(() => {
- spyOn(
+ it('Response is invalid if validateIdTokenAtHash is false', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
config.clientId = '';
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'id_token token';
config.autoCleanStateAfterAuthentication = false;
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(false)
);
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.returnValue(false);
- spyOn(
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
+ false
+ );
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- true
- );
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
- const logWarningSpy = spyOn(loggerService, 'logWarning').and.callFake(
- () => undefined
- );
+ const logWarningSpy = vi
+ .spyOn(loggerService, 'logWarning')
+ .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1860,7 +1931,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logWarningSpy).toHaveBeenCalledOnceWith(
+ expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config,
'authCallback incorrect at_hash'
);
@@ -1869,67 +1940,74 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false);
});
- }));
+ });
- it('should return valid result if validateIdTokenIss is false and iss_validation_off is true', waitForAsync(() => {
+ it('should return valid result if validateIdTokenIss is false and iss_validation_off is true', async () => {
config.issValidationOff = true;
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
false
);
- spyOn(tokenValidationService, 'hasIdTokenExpired').and.returnValue(false);
- spyOn(
+ vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
+ false
+ );
+ vi.spyOn(
tokenValidationService,
'validateAccessTokenNotExpired'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenAzpExistsIfMoreThanOneAud'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAzpValid').and.returnValue(
- true
- );
+ ).mockReturnValue(true);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateIdTokenAzpValid'
+ ).mockReturnValue(true);
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
- true
- );
- spyOn(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(true)
);
config.responseType = 'id_token token';
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
- const logDebugSpy = spyOn(loggerService, 'logDebug'); // .and.callFake(() => undefined);
+ const logDebugSpy = vi.spyOn(loggerService, 'logDebug'); // .mockImplementation(() => undefined);
const callbackContext = {
code: 'fdffsdfsdf',
@@ -1951,7 +2029,7 @@ describe('State Validation Service', () => {
);
stateObs$.subscribe((state) => {
- expect(logDebugSpy.calls.allArgs()).toEqual([
+ expect(logDebugSpy).toBeCalledWith([
[config, 'iss validation is turned off, this is not recommended!'],
[config, 'authCallback token(s) validated, continue'],
]);
@@ -1961,54 +2039,60 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBeDefined();
expect(state.idToken).toBe('id_tokenTEST');
});
- }));
+ });
- it('should return valid if there is no id_token', waitForAsync(() => {
- spyOn(
+ it('should return valid if there is no id_token', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
+ ).mockReturnValue(true);
config.responseType = 'code';
- spyOn(tokenHelperService, 'getPayloadFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
'decoded_id_token'
);
- spyOn(tokenValidationService, 'validateSignatureIdToken').and.returnValue(
- of(true)
- );
- spyOn(tokenValidationService, 'validateIdTokenNonce').and.returnValue(
- true
- );
- spyOn(tokenValidationService, 'validateRequiredIdToken').and.returnValue(
+ vi.spyOn(
+ tokenValidationService,
+ 'validateSignatureIdToken'
+ ).mockReturnValue(of(true));
+ vi.spyOn(tokenValidationService, 'validateIdTokenNonce').mockReturnValue(
true
);
+ vi.spyOn(
+ tokenValidationService,
+ 'validateRequiredIdToken'
+ ).mockReturnValue(true);
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
config.clientId = '';
- spyOn(
+ vi.spyOn(
tokenValidationService,
'validateIdTokenIatMaxOffset'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAud').and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenAud').mockReturnValue(
+ true
+ );
+ vi.spyOn(
tokenValidationService,
'validateIdTokenExpNotExpired'
- ).and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenIss').and.returnValue(true);
- spyOn(tokenValidationService, 'validateIdTokenAtHash').and.returnValue(
+ ).mockReturnValue(true);
+ vi.spyOn(tokenValidationService, 'validateIdTokenIss').mockReturnValue(
+ true
+ );
+ vi.spyOn(tokenValidationService, 'validateIdTokenAtHash').mockReturnValue(
of(true)
);
config.autoCleanStateAfterAuthentication = false;
- const readSpy = spyOn(storagePersistenceService, 'read');
+ const readSpy = vi.spyOn(storagePersistenceService, 'read');
readSpy
.withArgs('authWellKnownEndPoints', config)
- .and.returnValue(authWellKnownEndpoints);
+ .mockReturnValue(authWellKnownEndpoints);
readSpy
.withArgs('authStateControl', config)
- .and.returnValue('authStateControl');
- readSpy.withArgs('authNonce', config).and.returnValue('authNonce');
+ .mockReturnValue('authStateControl');
+ readSpy.withArgs('authNonce', config).mockReturnValue('authNonce');
const callbackContext = {
code: 'fdffsdfsdf',
@@ -2036,18 +2120,18 @@ describe('State Validation Service', () => {
expect(state.decodedIdToken).toBeDefined();
expect(state.authResponseIsValid).toBe(true);
});
- }));
+ });
- it('should return OK if disableIdTokenValidation is true', waitForAsync(() => {
- spyOn(
+ it('should return OK if disableIdTokenValidation is true', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
+ ).mockReturnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
config.responseType = 'id_token token';
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
@@ -2074,18 +2158,18 @@ describe('State Validation Service', () => {
expect(isValid.state).toBe(ValidationResult.Ok);
expect(isValid.authResponseIsValid).toBe(true);
});
- }));
+ });
- it('should return OK if disableIdTokenValidation is true', waitForAsync(() => {
- spyOn(
+ it('should return OK if disableIdTokenValidation is true', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
+ ).mockReturnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
config.responseType = 'id_token token';
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
@@ -2112,18 +2196,18 @@ describe('State Validation Service', () => {
expect(isValid.state).toBe(ValidationResult.Ok);
expect(isValid.authResponseIsValid).toBe(true);
});
- }));
+ });
- it('should return OK if disableIdTokenValidation is false but inrefreshtokenflow and no id token is returned', waitForAsync(() => {
- spyOn(
+ it('should return OK if disableIdTokenValidation is false but inrefreshtokenflow and no id token is returned', async () => {
+ vi.spyOn(
tokenValidationService,
'validateStateFromHashCallback'
- ).and.returnValue(true);
- spyOn(
+ ).mockReturnValue(true);
+ vi.spyOn(
flowHelper,
'isCurrentFlowImplicitFlowWithAccessToken'
- ).and.returnValue(false);
- spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
+ ).mockReturnValue(false);
+ vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
config.responseType = 'id_token token';
config.maxIdTokenIatOffsetAllowedInSeconds = 0;
@@ -2150,6 +2234,6 @@ describe('State Validation Service', () => {
expect(isValid.state).toBe(ValidationResult.Ok);
expect(isValid.authResponseIsValid).toBe(true);
});
- }));
+ });
});
});
diff --git a/src/validation/token-validation.service.spec.ts b/src/validation/token-validation.service.spec.ts
index f2abacb..8dfcb8f 100644
--- a/src/validation/token-validation.service.spec.ts
+++ b/src/validation/token-validation.service.spec.ts
@@ -1,8 +1,9 @@
-import { TestBed, waitForAsync } from '@angular/core/testing';
-import { of } from 'rxjs';
-import { mockProvider } from '../../test/auto-mock';
+import { TestBed } from '@/testing';
+import { lastValueFrom, of } from 'rxjs';
+import { vi } from 'vitest';
import { JwkExtractor } from '../extractors/jwk.extractor';
import { LoggerService } from '../logging/logger.service';
+import { mockProvider } from '../testing/mock';
import { CryptoService } from '../utils/crypto/crypto.service';
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
import { JwkWindowCryptoService } from './jwk-window-crypto.service';
@@ -498,7 +499,7 @@ describe('TokenValidationService', () => {
});
describe('validateSignatureIdToken', () => {
- it('returns false if no kwtKeys are passed', waitForAsync(() => {
+ it('returns false if no kwtKeys are passed', async () => {
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
'some-id-token',
null,
@@ -508,9 +509,9 @@ describe('TokenValidationService', () => {
valueFalse$.subscribe((valueFalse) => {
expect(valueFalse).toEqual(false);
});
- }));
+ });
- it('returns true if no idToken is passed', waitForAsync(() => {
+ it('returns true if no idToken is passed', async () => {
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
null as any,
'some-jwt-keys',
@@ -520,9 +521,9 @@ describe('TokenValidationService', () => {
valueFalse$.subscribe((valueFalse) => {
expect(valueFalse).toEqual(true);
});
- }));
+ });
- it('returns false if jwtkeys has no keys-property', waitForAsync(() => {
+ it('returns false if jwtkeys has no keys-property', async () => {
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
'some-id-token',
{ notKeys: '' },
@@ -532,10 +533,10 @@ describe('TokenValidationService', () => {
valueFalse$.subscribe((valueFalse) => {
expect(valueFalse).toEqual(false);
});
- }));
+ });
- it('returns false if header data has no header data', waitForAsync(() => {
- spyOn(tokenHelperService, 'getHeaderFromToken').and.returnValue({});
+ it('returns false if header data has no header data', async () => {
+ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({});
const jwtKeys = {
keys: 'someThing',
@@ -550,10 +551,10 @@ describe('TokenValidationService', () => {
valueFalse$.subscribe((valueFalse) => {
expect(valueFalse).toEqual(false);
});
- }));
+ });
- it('returns false if header data alg property does not exist in keyalgorithms', waitForAsync(() => {
- spyOn(tokenHelperService, 'getHeaderFromToken').and.returnValue({
+ it('returns false if header data alg property does not exist in keyalgorithms', async () => {
+ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
alg: 'NOT SUPPORTED ALG',
});
@@ -570,16 +571,16 @@ describe('TokenValidationService', () => {
valueFalse$.subscribe((valueFalse) => {
expect(valueFalse).toEqual(false);
});
- }));
+ });
it('returns false if header data has kid property and jwtKeys has same kid property but they are not valid with the token', (done) => {
const kid = '5626CE6A8F4F5FCD79C6642345282CA76D337548';
- spyOn(tokenHelperService, 'getHeaderFromToken').and.returnValue({
+ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
alg: 'RS256',
kid,
});
- spyOn(tokenHelperService, 'getSignatureFromToken').and.returnValue('');
+ vi.spyOn(tokenHelperService, 'getSignatureFromToken').mockReturnValue('');
const jwtKeys = {
keys: [
@@ -626,14 +627,14 @@ describe('TokenValidationService', () => {
keys: [key],
};
- spyOn(tokenHelperService, 'getHeaderFromToken').and.returnValue({
+ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
alg: 'RS256',
typ: 'JWT',
});
- spyOn(tokenHelperService, 'getSigningInputFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getSigningInputFromToken').mockReturnValue(
[idTokenParts[0], idTokenParts[1]].join('.')
);
- spyOn(tokenHelperService, 'getSignatureFromToken').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getSignatureFromToken').mockReturnValue(
idTokenParts[2]
);
@@ -668,22 +669,21 @@ describe('TokenValidationService', () => {
});
});
- it('returns false if sha is sha256 and generated hash does not equal atHash param', (done) => {
+ it('returns false if sha is sha256 and generated hash does not equal atHash param', async () => {
const accessToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
const atHash = 'bad';
- const result$ = tokenValidationService.validateIdTokenAtHash(
- accessToken,
- atHash,
- '256',
- { configId: 'configId1' }
+ const result = await lastValueFrom(
+ tokenValidationService.validateIdTokenAtHash(
+ accessToken,
+ atHash,
+ '256',
+ { configId: 'configId1' }
+ )
);
- result$.subscribe((result) => {
- expect(result).toEqual(false);
- done();
- });
+ expect(result).toEqual(false);
});
it('returns true if sha is sha256 and generated hash does equal atHash param', (done) => {
@@ -691,7 +691,7 @@ describe('TokenValidationService', () => {
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
const atHash = 'good';
- spyOn(jwtWindowCryptoService, 'generateAtHash').and.returnValues(
+ vi.spyOn(jwtWindowCryptoService, 'generateAtHash').mockReturnValues(
of('notEqualsGood'),
of('good')
);
@@ -770,7 +770,7 @@ describe('TokenValidationService', () => {
describe('validateIdTokenExpNotExpired', () => {
it('returns false when getTokenExpirationDate returns null', () => {
- spyOn(tokenHelperService, 'getTokenExpirationDate').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getTokenExpirationDate').mockReturnValue(
null as unknown as Date
);
const notExpired = tokenValidationService.validateIdTokenExpNotExpired(
@@ -848,7 +848,7 @@ describe('TokenValidationService', () => {
const idToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTMxMTY5NTAsImV4cCI6MjUyODI2NTc1MCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.GHxRo23NghUTTeZx6VIzTSf05JEeEn7z9YYyFLxWv6M';
- spyOn(tokenHelperService, 'getTokenExpirationDate').and.returnValue(
+ vi.spyOn(tokenHelperService, 'getTokenExpirationDate').mockReturnValue(
tokenExpires
);
diff --git a/tsconfig.json b/tsconfig.json
index 79ead0d..95f8a1d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,24 +3,28 @@
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"strict": true,
- "noEmit": true,
+ "declaration": true,
+ "declarationMap": true,
"sourceMap": true,
- "declaration": false,
+ "skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true,
- "skipLibCheck": true,
+ "emitDecoratorMetadata": true,
"moduleResolution": "bundler",
- "target": "ES2015",
+ "target": "ES2022",
"module": "ESNext",
"lib": ["ES2021", "DOM", "DOM.Iterable"],
"useDefineForClassFields": true,
- "allowImportingTsExtensions": true,
- "resolveJsonModule": true,
- "paths": {
- "injection-js": [
- "./node_modules/injection-js/lib"
- ]
- }
+ "resolveJsonModule": true
},
- "include": ["src"]
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
}
diff --git a/tsconfig.lib.json b/tsconfig.lib.json
index 6c61a1f..8d6cadb 100644
--- a/tsconfig.lib.json
+++ b/tsconfig.lib.json
@@ -1,12 +1,13 @@
{
- "extends": "./tsconfig.json",
"compilerOptions": {
- "outDir": "./dist/lib",
- "declaration": true,
- "declarationMap": true,
- "inlineSources": true,
- "types": ["node"],
- "lib": ["dom", "es2018"]
+ "composite": true,
+ "rootDir": ".",
+ "outDir": "./dist/tsc-lib",
+ "lib": ["dom", "es2018"],
+ "paths": {
+ "injection-js": ["./node_modules/injection-js/lib/index.ts"]
+ }
},
- "exclude": ["src/test.ts", "**/*.spec.ts"]
+ "include": ["src"],
+ "exclude": ["src/testing/**/*", "**/*.spec.ts"]
}
diff --git a/tsconfig.spec.json b/tsconfig.spec.json
index 5473296..aa0cca3 100644
--- a/tsconfig.spec.json
+++ b/tsconfig.spec.json
@@ -1,10 +1,24 @@
-/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
- "outDir": "./out-tsc/spec",
- "types": ["jasmine", "node"]
+ "rootDir": ".",
+ "composite": true,
+ "noUncheckedIndexedAccess": true,
+ "outDir": "./dist/tsc-test",
+ "types": ["vitest/globals", "node"],
+ "paths": {
+ "@/testing": ["./src/testing"],
+ "@/testing/*": ["./src/testing/*"],
+ "injection-js": ["./node_modules/injection-js/lib/index.ts"],
+ "oidc-client-rx": ["./src"],
+ "oidc-client-rx/*": ["./src/*"]
+ }
},
- "files": ["src/test.ts"],
- "include": ["**/*.spec.ts", "**/*.d.ts"]
+ "files": [],
+ "include": ["src/**/*.spec.ts", "src/testing"],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ }
+ ]
}