From 0d372de3c460efe814e9a90481f1c20842a827b8 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 15 Nov 2024 13:41:00 +0100 Subject: [PATCH 01/78] introduce spotless formatter --- backend/pom.xml | 28 +- backend/src/main/resources/formatting.xml | 380 ++++++++++++++++++++++ frontend/scripts/pre-commit | 12 +- 3 files changed, 404 insertions(+), 16 deletions(-) create mode 100644 backend/src/main/resources/formatting.xml diff --git a/backend/pom.xml b/backend/pom.xml index 8a47747d55..3ffbea1bb2 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -231,24 +231,32 @@ maven-surefire-plugin 3.5.2 - - net.revelc.code.formatter - formatter-maven-plugin - 2.24.1 - - ${maven.compiler.source} - ${maven.compiler.source} - ${maven.compiler.source} - + com.diffplug.spotless + spotless-maven-plugin + 2.43.0 code-format - format + apply + + + + 4.26 + ${project.basedir}/src/main/resources/formatting.xml + + + + java|javax,ch.puzzle,org,com,com.diffplug,,\#com.diffplug,\# + true + + + + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml new file mode 100644 index 0000000000..399b95d128 --- /dev/null +++ b/backend/src/main/resources/formatting.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index ac5a7fbde3..056309889c 100644 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -1,20 +1,20 @@ #!/bin/sh -projectPath=$PWD -addedFiles=$(git diff --cached --name-only --diff-filter=a) +gitBasePath=$(git rev-parse --show-toplevel) +addedFiles=$(git diff --cached --name-only --diff-filter=d) echo "*****Running prettier******" -cd $projectPath/frontend +cd $gitBasePath/frontend npm run format echo "*****Finish running prettier******" echo "*****Running maven formatter******" -cd $projectPath/backend -mvn formatter:format +cd $gitBasePath/backend +mvn spotless:apply echo "*****Finish running maven formatter******" echo "*****Adding changes to git******" -cd $projectPath +cd $gitBasePath git add $addedFiles echo "*****Formatted files added again******" From 51b41f9c7e4c9b266f5238745169bffcf402c99f Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 15 Nov 2024 13:50:24 +0100 Subject: [PATCH 02/78] update readme and pipeline --- .github/workflows/format-action.yml | 47 +++++------------------------ backend/README.md | 11 +++---- backend/pom.xml | 6 ++-- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/.github/workflows/format-action.yml b/.github/workflows/format-action.yml index 8ab0c9dd70..e57db39e56 100644 --- a/.github/workflows/format-action.yml +++ b/.github/workflows/format-action.yml @@ -3,7 +3,7 @@ name: 'Format' on: [push] jobs: - Frontend: + frontend: runs-on: ubuntu-latest defaults: run: @@ -15,33 +15,19 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22.10.0 + node-version: ${{vars.NODE_VERSION}} - name: Npm install run: npm ci - name: Format frontend - run: npm run format + run: npm run check - - name: Commit and Push formated frontend - shell: bash - env: - COMMITPREFIX: '[FM]' - run: | - git config --global user.email "actions@github.com" - git config --global user.name "GitHub Actions" - git add . || { - echo "No files were changed, so we did not commit anything" - exit 1 - } - git commit -m "$COMMITPREFIX Automated formating frontend" || { - echo "No changes to commit, skipping push" - exit 0 - } - git push -f - - Backend: + backend: runs-on: ubuntu-latest + defaults: + run: + working-directory: backend steps: - name: Checkout uses: actions/checkout@v4 @@ -55,21 +41,4 @@ jobs: settings-path: ${{github.workspace}} - name: Format backend - run: mvn formatter:format -f backend/pom.xml - - - name: Commit and Push formated backend - shell: bash - env: - COMMITPREFIX: '[FM]' - run: | - git config --global user.email "actions@github.com" - git config --global user.name "GitHub Actions" - git add . || { - echo "No files were changed, so we did not commit anything" - exit 1 - } - git commit -m "$COMMITPREFIX Automated formating backend" || { - echo "No changes to commit, skipping push" - exit 0 - } - git push -f \ No newline at end of file + run: mvn spotless:check \ No newline at end of file diff --git a/backend/README.md b/backend/README.md index 127c7150a1..b31e5267e7 100644 --- a/backend/README.md +++ b/backend/README.md @@ -33,17 +33,16 @@ USING DOCKER - backend/target Formatting: -- Check code formatting: `mvn formatter:validate` -- Format the code: `mvn formatter:format` +- Check code formatting: `mvn spotless:check` +- Format the code: `mvn spotless:apply` -The `compile` goal execute also a `formatter:format` goal. +The `compile` goal execute also a `spotless:apply` goal. Verify the Backend for coverage check: - `mvn clean verify` ## Formatting -We use the **formatter-maven-plugin** Plugin for formatting the Java code: -https://code.revelc.net/formatter-maven-plugin/ - +We use the **spotless** Plugin for formatting the Java code: +https://github.com/diffplug/spotless ## Build _tbd_ diff --git a/backend/pom.xml b/backend/pom.xml index 3ffbea1bb2..dd49b005f4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -313,9 +313,9 @@ - net.revelc.code.formatter - formatter-maven-plugin - 2.24.1 + com.diffplug.spotless + spotless-maven-plugin + 2.43.0 code-format From f754da40e16e1958ac9752694d2eb41923bed62d Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 18 Nov 2024 08:50:18 +0100 Subject: [PATCH 03/78] add typescript formatter --- backend/pom.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/backend/pom.xml b/backend/pom.xml index dd49b005f4..3bfd4b7634 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -256,6 +256,22 @@ + + + + src/**/*.ts + + + + + + + + + /* (C)$YEAR */ + (import|const|declare|export|var) + + From 19cd0440ab6b81dcc4de0f7ee26a785efc950834 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 18 Nov 2024 15:44:56 +0100 Subject: [PATCH 04/78] add frontedn config --- backend/pom.xml | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index 3bfd4b7634..14be852f4e 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -259,18 +259,35 @@ - src/**/*.ts + ../frontend/src/app/**/*.ts - - - - - - - /* (C)$YEAR */ - (import|const|declare|export|var) - + + + 8.30.0 + + + + { + env: { + browser: true, + es2021: true + }, + extends: 'standard-with-typescript', + overrides: [ + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: '../../frontend/tsconfig.json', + }, + rules: { + } + } + + + ${project.basedir}/../frontend/tsconfig.json + From b9186b941d9044c24dc903a976b76a0e3984f14e Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 18 Nov 2024 16:39:58 +0100 Subject: [PATCH 05/78] update tsconfig.json --- frontend/tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index c4e3ae25fd..d5a401e42b 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -22,7 +22,9 @@ "resolveJsonModule": true, "esModuleInterop": true, "useDefineForClassFields": false, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "noUnusedLocals": true, + "noUnusedParameters": true }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, From c837bdf450b85cd815051da28bbb5ae502e2b380 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 18 Nov 2024 17:02:52 +0100 Subject: [PATCH 06/78] install eslint for formating --- backend/pom.xml | 33 --------------------------------- frontend/eslint.config.mjs | 8 ++++++++ frontend/package.json | 10 ++++++---- frontend/tsconfig.json | 2 -- 4 files changed, 14 insertions(+), 39 deletions(-) create mode 100644 frontend/eslint.config.mjs diff --git a/backend/pom.xml b/backend/pom.xml index 14be852f4e..dd49b005f4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -256,39 +256,6 @@ - - - - ../frontend/src/app/**/*.ts - - - - - 8.30.0 - - - - { - env: { - browser: true, - es2021: true - }, - extends: 'standard-with-typescript', - overrides: [ - ], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: '../../frontend/tsconfig.json', - }, - rules: { - } - } - - - ${project.basedir}/../frontend/tsconfig.json - - diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs new file mode 100644 index 0000000000..160194cb71 --- /dev/null +++ b/frontend/eslint.config.mjs @@ -0,0 +1,8 @@ + +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommended, +); \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 83591bfc76..3045733ecd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,9 +13,8 @@ "cypress:run": "cypress run --browser chrome", "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "prettier --write \"./**/*.{js,ts,json,css,scss,html,md,yaml}\"", - "check": "prettier --check \"./**/*.{js,ts,json,css,scss,html,md,yaml}\"", - "format:upgrade": "npm install --save-exact prettier@latest && npm run format", + "format": "eslint --fix .", + "check": "eslint .", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", "e2e": "ng e2e" @@ -48,16 +47,19 @@ "@angular/compiler-cli": "^18.2.8", "@cypress/schematic": "^2.5.2", "@cypress/skip-test": "^2.6.1", + "@eslint/js": "^9.15.0", + "@types/eslint__js": "^8.42.3", "@types/jest": "^29.5.13", "@types/uuid": "^10.0.0", "browserslist": "^4.24.2", "cypress": "^13.15.0", "cypress-real-events": "^1.13.0", + "eslint": "^9.14.0", "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", - "prettier": "^3.3.3", "typescript": "^5.5.4", + "typescript-eslint": "^8.14.0", "uuid": "^11.0.0" }, "jest": { diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index d5a401e42b..2e5b345397 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -23,8 +23,6 @@ "esModuleInterop": true, "useDefineForClassFields": false, "allowSyntheticDefaultImports": true, - "noUnusedLocals": true, - "noUnusedParameters": true }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, From 51dc75a1d1af394809729e9d60445f2e8f068770 Mon Sep 17 00:00:00 2001 From: Miguel Lehmann Date: Tue, 19 Nov 2024 09:15:23 +0100 Subject: [PATCH 07/78] update typescript-eslint to 8.15.0 --- frontend/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 3045733ecd..bae263d760 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,6 +34,7 @@ "@angular/router": "^18.2.8", "@ngx-translate/core": "^16.0.0", "@ngx-translate/http-loader": "^16.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", "moment": "^2.30.1", @@ -59,7 +60,7 @@ "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "typescript": "^5.5.4", - "typescript-eslint": "^8.14.0", + "typescript-eslint": "^8.15.0", "uuid": "^11.0.0" }, "jest": { From a7d6009155209e1e0b5a321c65e5f3211f5927f5 Mon Sep 17 00:00:00 2001 From: Miguel Lehmann Date: Tue, 19 Nov 2024 10:28:52 +0100 Subject: [PATCH 08/78] edit config --- frontend/eslint.config.mjs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 160194cb71..9345f95782 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,8 +1,14 @@ import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; +import {rules} from "@typescript-eslint/eslint-plugin"; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, -); \ No newline at end of file + { + rules: { + "unused-imports/no-unused-imports": "error", + } + } +); From d84ee2eacce573f119c1c9c27fbbae4f9b297bf4 Mon Sep 17 00:00:00 2001 From: Miguel Lehmann Date: Tue, 19 Nov 2024 10:43:46 +0100 Subject: [PATCH 09/78] put unused-imports plugin into config --- frontend/eslint.config.mjs | 5 ++++- frontend/package.json | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 9345f95782..a52431b4e2 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,12 +1,15 @@ import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; -import {rules} from "@typescript-eslint/eslint-plugin"; +import unusedImports from "eslint-plugin-unused-imports"; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, { + plugins: { + "unused-imports": unusedImports, + }, rules: { "unused-imports/no-unused-imports": "error", } diff --git a/frontend/package.json b/frontend/package.json index bae263d760..ea9687964a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -56,6 +56,7 @@ "cypress": "^13.15.0", "cypress-real-events": "^1.13.0", "eslint": "^9.14.0", + "eslint-plugin-unused-imports": "^4.1.4", "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", From 0d760b3e038cf21bf173fd618cd40511f45fce2a Mon Sep 17 00:00:00 2001 From: Miguel Lehmann Date: Tue, 19 Nov 2024 14:20:28 +0100 Subject: [PATCH 10/78] change config for spec files --- frontend/eslint.config.mjs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index a52431b4e2..9ee4c8235a 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -3,15 +3,22 @@ import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; import unusedImports from "eslint-plugin-unused-imports"; + export default tseslint.config( - eslint.configs.recommended, - ...tseslint.configs.recommended, + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.spec.ts'], + rules: { + "@typescript-eslint/no-explicit-any": "off" + }, + }, { plugins: { - "unused-imports": unusedImports, + 'unused-imports': unusedImports, }, rules: { - "unused-imports/no-unused-imports": "error", - } + 'unused-imports/no-unused-imports': 'error', + }, } ); From a018423e45eefae4b10fd0849f98c9e06634fa5a Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 08:40:02 +0100 Subject: [PATCH 11/78] add stylistic plugin to eslnt --- frontend/eslint.config.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 9ee4c8235a..b436711f89 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -2,6 +2,8 @@ import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; import unusedImports from "eslint-plugin-unused-imports"; +import stylistic from '@stylistic/eslint-plugin' + export default tseslint.config( @@ -16,9 +18,13 @@ export default tseslint.config( { plugins: { 'unused-imports': unusedImports, + '@stylistic': stylistic }, rules: { 'unused-imports/no-unused-imports': 'error', + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-expressions": "off", + "no-undef": "off", }, } ); From c92dbe93952765dc58592c595b6436e6b34faeac Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 08:52:55 +0100 Subject: [PATCH 12/78] add eslint stylistic rules --- frontend/eslint.config.mjs | 22 +++++++++++----------- frontend/package.json | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index b436711f89..b797b944ab 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,24 +1,24 @@ -import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; +import eslint from "@eslint/js"; +import tsEslint from "typescript-eslint"; import unusedImports from "eslint-plugin-unused-imports"; -import stylistic from '@stylistic/eslint-plugin' +import stylistic from "@stylistic/eslint-plugin"; - -export default tseslint.config( +export default tsEslint.config( eslint.configs.recommended, - ...tseslint.configs.recommended, - { - files: ['**/*.spec.ts'], - rules: { - "@typescript-eslint/no-explicit-any": "off" + ...tsEslint.configs.recommended, + stylistic.configs['all-flat'], + { + files: ['**/*.spec.ts'], + rules: { + "@typescript-eslint/no-explicit-any": "off" }, }, { plugins: { 'unused-imports': unusedImports, - '@stylistic': stylistic + '@stylistic': stylistic }, rules: { 'unused-imports/no-unused-imports': 'error', diff --git a/frontend/package.json b/frontend/package.json index ea9687964a..5baa5bf04c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,6 +34,7 @@ "@angular/router": "^18.2.8", "@ngx-translate/core": "^16.0.0", "@ngx-translate/http-loader": "^16.0.0", + "@stylistic/eslint-plugin": "^2.11.0", "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", From cf05568c12bb504522c444b3419dcaaa104122ac Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 09:26:52 +0100 Subject: [PATCH 13/78] update config for eslint stylic --- frontend/eslint.config.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index b797b944ab..ee14055024 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -25,6 +25,10 @@ export default tsEslint.config( "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-expressions": "off", "no-undef": "off", + "@stylistic/function-call-argument-newline": ["error", "never"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }] }, } ); From 7a87478ec431ef55fb5ffd50cf8f7aac5b4fabae Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 09:40:12 +0100 Subject: [PATCH 14/78] styling indent set to 2 --- frontend/eslint.config.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index ee14055024..65d7cbb53e 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -28,7 +28,9 @@ export default tsEslint.config( "@stylistic/function-call-argument-newline": ["error", "never"], "@stylistic/padded-blocks": ["error", "never"], "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }] + "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], + "@stylistic/indent": ["error", 2], + // "@stylistic/quotes":"off" }, } ); From 732ecc6e6bcc410077e28ff4523611c06aad2895 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 10:09:30 +0100 Subject: [PATCH 15/78] add html formatting --- frontend/eslint.config.mjs | 14 +++++++++++--- frontend/package.json | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 65d7cbb53e..e1123b2735 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,9 +1,8 @@ - import eslint from "@eslint/js"; import tsEslint from "typescript-eslint"; import unusedImports from "eslint-plugin-unused-imports"; import stylistic from "@stylistic/eslint-plugin"; - +import html from "@html-eslint/eslint-plugin"; export default tsEslint.config( eslint.configs.recommended, @@ -13,8 +12,17 @@ export default tsEslint.config( files: ['**/*.spec.ts'], rules: { "@typescript-eslint/no-explicit-any": "off" + }, + }, + { + ...html.configs["flat/recommended"], + files: ["**/*.html"], + rules: { + ...html.configs["flat/recommended"].rules, + "@html-eslint/indent": ["error",2], + + } }, - }, { plugins: { 'unused-imports': unusedImports, diff --git a/frontend/package.json b/frontend/package.json index 5baa5bf04c..37e8e3198b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -50,6 +50,8 @@ "@cypress/schematic": "^2.5.2", "@cypress/skip-test": "^2.6.1", "@eslint/js": "^9.15.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", "@types/eslint__js": "^8.42.3", "@types/jest": "^29.5.13", "@types/uuid": "^10.0.0", From 54ca0356eeef6a305a74de265889bbeb1b38f78d Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 10:27:24 +0100 Subject: [PATCH 16/78] extract eslint format in seperated command --- frontend/package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 37e8e3198b..f5a60fee2d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,8 +13,11 @@ "cypress:run": "cypress run --browser chrome", "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "eslint --fix .", - "check": "eslint .", + "format": "npm run esl-format", + "check": "npm run es-check", + "esl-format": "eslint --fix .", + "es-check": "eslint .", + "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", "e2e": "ng e2e" From 91daa77b7a315fb6cc34247eed38bf6600d4d0fb Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 10:39:22 +0100 Subject: [PATCH 17/78] readd prettier for css json and yaml --- frontend/package-lock.json | 16 ++++++++++++++++ frontend/package.json | 8 +++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index df9280d097..53f2b44c02 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -15896,6 +15896,22 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index f5a60fee2d..12e095baf3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,11 +13,12 @@ "cypress:run": "cypress run --browser chrome", "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "npm run esl-format", - "check": "npm run es-check", + "format": "npm run esl-format && npm run prettier-format", + "check": "npm run es-check && npm run prettier-check", "esl-format": "eslint --fix .", "es-check": "eslint .", - + "prettier-format": "prettier --write \"./**/*.{json,css,scss,md,yaml,yml}\"", + "prettier-check": "prettier --check \"./**/*.{json,css,scss,md,yaml,yml}\"", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", "e2e": "ng e2e" @@ -66,6 +67,7 @@ "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", + "prettier": "^3.3.3", "typescript": "^5.5.4", "typescript-eslint": "^8.15.0", "uuid": "^11.0.0" From 051c2e7732d9862576c8b7d3e9e873cd9d0d7e5c Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 10:47:22 +0100 Subject: [PATCH 18/78] update eslint config --- frontend/eslint.config.mjs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index e1123b2735..ded53f4afe 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -7,7 +7,10 @@ import html from "@html-eslint/eslint-plugin"; export default tsEslint.config( eslint.configs.recommended, ...tsEslint.configs.recommended, - stylistic.configs['all-flat'], + { + ...stylistic.configs['all-flat'], + files: ['**/*.ts'], + }, { files: ['**/*.spec.ts'], rules: { @@ -38,7 +41,7 @@ export default tsEslint.config( "@stylistic/dot-location": ["error", "property"], "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], "@stylistic/indent": ["error", 2], - // "@stylistic/quotes":"off" + "@stylistic/quotes":["error","double"] }, } ); From 174ee5bbe1da6421363c5eb2c683d3a6ca6ad586 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 11:04:01 +0100 Subject: [PATCH 19/78] disable check for multipline tenary --- frontend/eslint.config.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index ded53f4afe..cffd667849 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -41,7 +41,8 @@ export default tsEslint.config( "@stylistic/dot-location": ["error", "property"], "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], "@stylistic/indent": ["error", 2], - "@stylistic/quotes":["error","double"] + "@stylistic/quotes":["error","double"], + "@stylistic/multiline-ternary": ["off"], }, } ); From b454489403b2fd6fecf0eaf065ad1a66bd65f0cc Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 11:41:54 +0100 Subject: [PATCH 20/78] refactor config to extract rules to apply only on ts files --- frontend/eslint.config.mjs | 64 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index cffd667849..38261eb1c8 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -5,44 +5,42 @@ import stylistic from "@stylistic/eslint-plugin"; import html from "@html-eslint/eslint-plugin"; export default tsEslint.config( - eslint.configs.recommended, - ...tsEslint.configs.recommended, - { - ...stylistic.configs['all-flat'], - files: ['**/*.ts'], - }, - { - files: ['**/*.spec.ts'], + eslint.configs.recommended, ...tsEslint.configs.recommended, { + ...stylistic.configs["all-flat"], + files: ["**/*.ts"], rules: { - "@typescript-eslint/no-explicit-any": "off" - }, - }, - { - ...html.configs["flat/recommended"], - files: ["**/*.html"], - rules: { - ...html.configs["flat/recommended"].rules, - "@html-eslint/indent": ["error",2], - - } - }, - { - plugins: { - 'unused-imports': unusedImports, - '@stylistic': stylistic - }, - rules: { - 'unused-imports/no-unused-imports': 'error', + "unused-imports/no-unused-imports": "error", + //disable rules so eslint passes, probably fix later "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-expressions": "off", "no-undef": "off", - "@stylistic/function-call-argument-newline": ["error", "never"], - "@stylistic/padded-blocks": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], - "@stylistic/indent": ["error", 2], - "@stylistic/quotes":["error","double"], + "@typescript-eslint/no-explicit-any": "off", + //stylistic rules + "@stylistic/function-call-argument-newline": ["error", "never"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], + "@stylistic/indent": ["error", 2], + "@stylistic/quotes":["error","double"], "@stylistic/multiline-ternary": ["off"], + }, + }, { + files: ["**/*.spec.ts"], + rules: { + "@typescript-eslint/no-explicit-any": "off" + }, + }, { + ...html.configs["flat/recommended"], + files: ["**/*.html"], + rules: { + ...html.configs["flat/recommended"].rules, + "@html-eslint/indent": ["error",2], + + } + }, { + plugins: { + "unused-imports": unusedImports, + "@stylistic": stylistic }, } ); From aa23608086195156bbe67e976299742996dfe3e0 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 22 Nov 2024 11:48:29 +0100 Subject: [PATCH 21/78] allow arguments --- frontend/eslint.config.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 38261eb1c8..d93034e970 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -27,7 +27,9 @@ export default tsEslint.config( }, { files: ["**/*.spec.ts"], rules: { - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "prefer-rest-params": "off", + }, }, { ...html.configs["flat/recommended"], From f70eafac03027c7a0ca3b35132aab4867209f0e8 Mon Sep 17 00:00:00 2001 From: Jannik Pulfer Date: Fri, 22 Nov 2024 15:32:23 +0100 Subject: [PATCH 22/78] Update excluded eslint rules that we want to resolve in follow up ticket --- frontend/eslint.config.mjs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index d93034e970..ced92f755b 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -10,11 +10,13 @@ export default tsEslint.config( files: ["**/*.ts"], rules: { "unused-imports/no-unused-imports": "error", - //disable rules so eslint passes, probably fix later + // ToDo: Disable rules so eslint passes, fix in followup ticket "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-expressions": "off", "no-undef": "off", "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-namespace": "off", + "prefer-rest-params": "off", //stylistic rules "@stylistic/function-call-argument-newline": ["error", "never"], "@stylistic/padded-blocks": ["error", "never"], @@ -29,15 +31,17 @@ export default tsEslint.config( rules: { "@typescript-eslint/no-explicit-any": "off", "prefer-rest-params": "off", - }, }, { ...html.configs["flat/recommended"], files: ["**/*.html"], rules: { ...html.configs["flat/recommended"].rules, + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@html-eslint/require-img-alt": "off", + "@html-eslint/element-newline": "off", + //stylistic rules "@html-eslint/indent": ["error",2], - } }, { plugins: { From 82a3e86e3872f7ad2a879f26edc9f2de2e70e3e3 Mon Sep 17 00:00:00 2001 From: Jannik Pulfer Date: Fri, 22 Nov 2024 15:45:08 +0100 Subject: [PATCH 23/78] Fix sentence in readme --- backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/README.md b/backend/README.md index b31e5267e7..58b7d8f264 100644 --- a/backend/README.md +++ b/backend/README.md @@ -36,7 +36,7 @@ Formatting: - Check code formatting: `mvn spotless:check` - Format the code: `mvn spotless:apply` -The `compile` goal execute also a `spotless:apply` goal. +We also run the formatter with `spotless:apply` in the `compile` goal. Verify the Backend for coverage check: - `mvn clean verify` From 73686587b16491f4bd2dca64460d476251782381 Mon Sep 17 00:00:00 2001 From: Jannik Pulfer Date: Mon, 25 Nov 2024 08:31:08 +0100 Subject: [PATCH 24/78] Allow ts-ignores --- frontend/eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index ced92f755b..f62d12b602 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -13,6 +13,7 @@ export default tsEslint.config( // ToDo: Disable rules so eslint passes, fix in followup ticket "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-expressions": "off", + "@typescript-eslint/ban-ts-comment": "off", "no-undef": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-namespace": "off", From 169469f349b5a57d3690918fd3e52c763a9851f8 Mon Sep 17 00:00:00 2001 From: Miguel Lehmann Date: Mon, 25 Nov 2024 15:48:04 +0100 Subject: [PATCH 25/78] remove unnecessary comma --- frontend/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 2e5b345397..c4e3ae25fd 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -22,7 +22,7 @@ "resolveJsonModule": true, "esModuleInterop": true, "useDefineForClassFields": false, - "allowSyntheticDefaultImports": true, + "allowSyntheticDefaultImports": true }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, From 71545de559811e973e998890cfab873da1d69869 Mon Sep 17 00:00:00 2001 From: Jannik Pulfer Date: Wed, 27 Nov 2024 11:08:55 +0100 Subject: [PATCH 26/78] Replace javax with jakarta in import order property of formatter --- backend/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pom.xml b/backend/pom.xml index dd49b005f4..deae6272cf 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -251,7 +251,7 @@ - java|javax,ch.puzzle,org,com,com.diffplug,,\#com.diffplug,\# + java|jakarta,ch.puzzle,org,com,com.diffplug,,\#com.diffplug,\# true From de1b9d8724ce27fb6c82aac71f16c044bbaa2e6a Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 10:01:03 +0100 Subject: [PATCH 27/78] get all changes from apply branch --- backend/README.md | 10 +- .../main/resources/formatters/Default-2.xml | 380 ++++++++++++++++ .../src/main/resources/formatters/default.xml | 380 ++++++++++++++++ backend/src/main/resources/formatting.xml | 419 +++--------------- frontend/package.json | 1 + frontend/scripts/pre-commit | 3 +- 6 files changed, 825 insertions(+), 368 deletions(-) create mode 100644 backend/src/main/resources/formatters/Default-2.xml create mode 100644 backend/src/main/resources/formatters/default.xml diff --git a/backend/README.md b/backend/README.md index 58b7d8f264..21996bb741 100644 --- a/backend/README.md +++ b/backend/README.md @@ -42,7 +42,15 @@ Verify the Backend for coverage check: - `mvn clean verify` ## Formatting -We use the **spotless** Plugin for formatting the Java code: +We use the ***spotless*** Plugin for formatting the Java code: https://github.com/diffplug/spotless + +### How to update the spotless configuration using intelij: +- Open `Go to Settings -> Editor -> Code styles -> Java` +- Select the default project config and export it to a file +- Then make the changes you want to the code style config ***HIT APPLY*** and then export it to a file +- Then run the following command `git --no-pager diff --no-index -U0 default.xml changed.xml | egrep '^.[[[:digit:]]+m\+' | less -R | diff-so-fancy` to see the changes +- +- then copy all additions to the formatter file in the backend project ## Build _tbd_ diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml new file mode 100644 index 0000000000..347a89a3e3 --- /dev/null +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml new file mode 100644 index 0000000000..ba1d2e1188 --- /dev/null +++ b/backend/src/main/resources/formatters/default.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 399b95d128..c3b58c6e1a 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -1,380 +1,67 @@ - + - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - \ No newline at end of file + diff --git a/frontend/package.json b/frontend/package.json index 12e095baf3..fedb161ffe 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,6 +15,7 @@ "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", "format": "npm run esl-format && npm run prettier-format", "check": "npm run es-check && npm run prettier-check", + "esl-format-specific": "eslint --fix ", "esl-format": "eslint --fix .", "es-check": "eslint .", "prettier-format": "prettier --write \"./**/*.{json,css,scss,md,yaml,yml}\"", diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 056309889c..00b16e0929 100644 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -5,7 +5,8 @@ addedFiles=$(git diff --cached --name-only --diff-filter=d) echo "*****Running prettier******" cd $gitBasePath/frontend -npm run format +npm run esl-format-specific $addedFiles +npm run prettier-format $addedFiles echo "*****Finish running prettier******" echo "*****Running maven formatter******" From ea79473352f525ff540b6421497e85fbb68b8f62 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 10:06:57 +0100 Subject: [PATCH 28/78] update precommit hook --- frontend/scripts/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 00b16e0929..38d8f6fe5c 100644 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -11,7 +11,7 @@ echo "*****Finish running prettier******" echo "*****Running maven formatter******" cd $gitBasePath/backend -mvn spotless:apply +mvn spotless:apply -DspotlessFiles=$addedFiles echo "*****Finish running maven formatter******" echo "*****Adding changes to git******" From eeec780549c662ac4af9097216bcafbadc9fc8cd Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 10:27:54 +0100 Subject: [PATCH 29/78] update backend formatter --- .../java/ch/puzzle/okr/ForwardFilter.java | 11 +++------- .../main/resources/formatters/Default-2.xml | 20 +++++++++---------- .../src/main/resources/formatters/default.xml | 2 +- backend/src/main/resources/formatting.xml | 4 ++-- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java index 2e517f4d59..c5c8368a11 100644 --- a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java +++ b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java @@ -1,18 +1,13 @@ package ch.puzzle.okr; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; +import java.io.IOException; +import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; import org.springframework.web.filter.GenericFilterBean; -import java.io.IOException; -import java.util.Arrays; - public class ForwardFilter extends GenericFilterBean { private static final Logger logger = LoggerFactory.getLogger(ForwardFilter.class); diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml index 347a89a3e3..e1155290b7 100644 --- a/backend/src/main/resources/formatters/Default-2.xml +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -1,6 +1,6 @@ - + @@ -294,21 +294,21 @@ - - + + - - + + - + - + - - - + + + diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml index ba1d2e1188..9d22dd95d5 100644 --- a/backend/src/main/resources/formatters/default.xml +++ b/backend/src/main/resources/formatters/default.xml @@ -1,6 +1,6 @@ - + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index c3b58c6e1a..68eac05326 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -26,8 +26,8 @@ - - + + From aa20815e677e1e0cbadcf72f1b7fa67c2a18004b Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 10:34:11 +0100 Subject: [PATCH 30/78] update java import order to alphabetically --- backend/pom.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index deae6272cf..ce2dfb93be 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -250,10 +250,7 @@ ${project.basedir}/src/main/resources/formatting.xml - - java|jakarta,ch.puzzle,org,com,com.diffplug,,\#com.diffplug,\# - true - + From ef544a3a1b2584e360b1780e085708534486f182 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 13:48:10 +0100 Subject: [PATCH 31/78] fix backend formatter for annotations --- backend/pom.xml | 2 +- .../java/ch/puzzle/okr/models/Objective.java | 42 +++++++++++-------- .../main/resources/formatters/Default-2.xml | 4 +- .../src/main/resources/formatters/default.xml | 12 +++--- backend/src/main/resources/formatting.xml | 23 ++++++++-- 5 files changed, 54 insertions(+), 29 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index ce2dfb93be..15d04270d9 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -248,10 +248,10 @@ 4.26 ${project.basedir}/src/main/resources/formatting.xml + - diff --git a/backend/src/main/java/ch/puzzle/okr/models/Objective.java b/backend/src/main/java/ch/puzzle/okr/models/Objective.java index 85a96b59dd..6d080d82f3 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Objective.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Objective.java @@ -1,15 +1,12 @@ package ch.puzzle.okr.models; import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - +import jakarta.validation.constraints.*; import java.time.LocalDateTime; import java.util.Objects; @Entity -@Table(indexes = { @Index(name = "idx_objective_title", columnList = "title") }) +@Table(indexes = {@Index(name = "idx_objective_title", columnList = "title")}) public class Objective implements WriteableInterface { @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "sequence_objective") @@ -163,30 +160,41 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "Objective{" + "id=" + id + ", version=" + version + ", title='" + title + '\'' + ", createdBy=" - + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' - + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" - + modifiedBy + ", writeable=" + writeable + '\'' + '}'; + + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' + + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" + + modifiedBy + ", writeable=" + writeable + '\'' + '}'; } @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } Objective objective = (Objective) o; return Objects.equals(id, objective.id) && version == objective.version - && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) - && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) - && Objects.equals(description, objective.description) - && Objects.equals(modifiedOn, objective.modifiedOn) && state == objective.state - && Objects.equals(createdOn, objective.createdOn) && Objects.equals(modifiedBy, objective.modifiedBy); + && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) + && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) + && Objects.equals(description, objective.description) && Objects.equals(modifiedOn, objective.modifiedOn) + && state == objective.state && Objects.equals(createdOn, objective.createdOn) + && Objects.equals(modifiedBy, objective.modifiedBy); } @Override public int hashCode() { - return Objects.hash(id, version, title, createdBy, team, quarter, description, modifiedOn, state, createdOn, - modifiedBy); + return Objects.hash(id, + version, + title, + createdBy, + team, + quarter, + description, + modifiedOn, + state, + createdOn, + modifiedBy); } public static final class Builder { diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml index e1155290b7..d13b05543d 100644 --- a/backend/src/main/resources/formatters/Default-2.xml +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -270,7 +270,7 @@ - + @@ -345,7 +345,7 @@ - + diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml index 9d22dd95d5..8e460f679e 100644 --- a/backend/src/main/resources/formatters/default.xml +++ b/backend/src/main/resources/formatters/default.xml @@ -270,7 +270,7 @@ - + @@ -295,9 +295,9 @@ - + - + @@ -343,11 +343,11 @@ - + - + - + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 68eac05326..4cf5577296 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -52,12 +52,29 @@ + + + + + + + + + + + + - - - + + + + + + + + From 567c2c30f6345a0cbf70dc79237a785ce5a3e61e Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 14:08:11 +0100 Subject: [PATCH 32/78] update formatting config to fix indentation of annonation params --- backend/src/main/resources/formatting.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 4cf5577296..295b298f47 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -61,7 +61,6 @@ - @@ -73,7 +72,6 @@ - From 08bf454a1ffe622fe82994d4e27dd4d692db6dfd Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 15:49:41 +0100 Subject: [PATCH 33/78] update formatter to improve parameter formatting --- .../main/resources/formatters/Default-2.xml | 48 +++++++++---------- .../src/main/resources/formatters/default.xml | 28 +++++------ backend/src/main/resources/formatting.xml | 24 ++++++++++ 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml index d13b05543d..9cd67f95a0 100644 --- a/backend/src/main/resources/formatters/Default-2.xml +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -37,17 +37,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -268,28 +268,28 @@ - + - + - - - - - - - - - + + + + + + + + + - + @@ -346,7 +346,7 @@ - + diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml index 8e460f679e..51bdec325c 100644 --- a/backend/src/main/resources/formatters/default.xml +++ b/backend/src/main/resources/formatters/default.xml @@ -268,24 +268,24 @@ - + - + - - - - - - - - - + + + + + + + + + @@ -343,11 +343,11 @@ - + - - + + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 295b298f47..22dbd8b75a 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -61,6 +61,7 @@ + @@ -73,10 +74,33 @@ + + + + + + + + + + + + + + + + + + + + + + + From 24f16cb3cc50be3b5ddbf90875ddcfaf8a30eff4 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 9 Dec 2024 16:42:12 +0100 Subject: [PATCH 34/78] update parameter formatting --- backend/README.md | 3 +- backend/pom.xml | 2 +- .../main/resources/formatters/Default-2.xml | 30 +++++++++---------- .../src/main/resources/formatters/default.xml | 2 +- backend/src/main/resources/formatting.xml | 1 + 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/backend/README.md b/backend/README.md index 21996bb741..411c2aebf6 100644 --- a/backend/README.md +++ b/backend/README.md @@ -49,8 +49,7 @@ https://github.com/diffplug/spotless - Open `Go to Settings -> Editor -> Code styles -> Java` - Select the default project config and export it to a file - Then make the changes you want to the code style config ***HIT APPLY*** and then export it to a file -- Then run the following command `git --no-pager diff --no-index -U0 default.xml changed.xml | egrep '^.[[[:digit:]]+m\+' | less -R | diff-so-fancy` to see the changes -- +- Then run the following command `git --no-pager diff --no-index -U0 default.xml changed.xml | egrep '^\+' | diff-so-fancy` to see the changes - then copy all additions to the formatter file in the backend project ## Build _tbd_ diff --git a/backend/pom.xml b/backend/pom.xml index 15d04270d9..5f01739b9c 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -248,7 +248,7 @@ 4.26 ${project.basedir}/src/main/resources/formatting.xml - + diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml index 9cd67f95a0..2ac9d298ae 100644 --- a/backend/src/main/resources/formatters/Default-2.xml +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -37,17 +37,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -289,16 +289,16 @@ - + - + - + @@ -346,7 +346,7 @@ - + diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml index 51bdec325c..f3fba4b74f 100644 --- a/backend/src/main/resources/formatters/default.xml +++ b/backend/src/main/resources/formatters/default.xml @@ -346,7 +346,7 @@ - + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 22dbd8b75a..48bcc82680 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -99,6 +99,7 @@ + From 3fb9ef82678116fb1d251440c85cb625cd3b9349 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 07:24:54 +0100 Subject: [PATCH 35/78] update formatter --- .../main/resources/formatters/Default-2.xml | 30 +++++++++---------- .../src/main/resources/formatters/default.xml | 24 +++++++-------- backend/src/main/resources/formatting.xml | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml index 2ac9d298ae..a5ae218a63 100644 --- a/backend/src/main/resources/formatters/Default-2.xml +++ b/backend/src/main/resources/formatters/Default-2.xml @@ -37,17 +37,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -289,23 +289,23 @@ - + - + - + - + diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml index f3fba4b74f..8eb1587675 100644 --- a/backend/src/main/resources/formatters/default.xml +++ b/backend/src/main/resources/formatters/default.xml @@ -37,17 +37,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -289,7 +289,7 @@ - + diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 48bcc82680..a4dee13c01 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -25,7 +25,7 @@ - + From 528811c6528f3dd7ca9bd103a49dceed1d2e015f Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 07:55:57 +0100 Subject: [PATCH 36/78] add space after array initializer --- backend/src/main/resources/formatting.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index a4dee13c01..28875c862f 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -102,6 +102,10 @@ + + + + From da8aad69a53bd202a706110eabc736c8fe815067 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 08:02:56 +0100 Subject: [PATCH 37/78] update precommit hook --- frontend/scripts/pre-commit | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 38d8f6fe5c..a181f4911b 100644 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -1,21 +1,22 @@ #!/bin/sh gitBasePath=$(git rev-parse --show-toplevel) -addedFiles=$(git diff --cached --name-only --diff-filter=d) +addedFiles=$(git diff --cached --name-only --diff-filter=d --line-prefix="${gitBasePath}"/) echo "*****Running prettier******" -cd $gitBasePath/frontend -npm run esl-format-specific $addedFiles -npm run prettier-format $addedFiles +cd "$gitBasePath"/frontend || exit +npm run esl-format-specific "$addedFiles" +npm run prettier-format "$addedFiles" echo "*****Finish running prettier******" echo "*****Running maven formatter******" -cd $gitBasePath/backend -mvn spotless:apply -DspotlessFiles=$addedFiles +cd "$gitBasePath" || exit +mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$addedFiles" echo "*****Finish running maven formatter******" echo "*****Adding changes to git******" -cd $gitBasePath +cd "$gitBasePath" || exit +# shellcheck disable=SC2086 git add $addedFiles echo "*****Formatted files added again******" From e6a7b0a0f234f89b069cbadb6e9b4bb2071e5c0b Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 08:44:09 +0100 Subject: [PATCH 38/78] precommit hook only updates changed files --- frontend/scripts/pre-commit | 47 ++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) mode change 100644 => 100755 frontend/scripts/pre-commit diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit old mode 100644 new mode 100755 index a181f4911b..f2894359e5 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -1,24 +1,53 @@ #!/bin/sh +GIT_BASE_PATH=$(git rev-parse --show-toplevel) +BACKEND_PATH="$GIT_BASE_PATH"/backend +FRONTEND_PATH="$GIT_BASE_PATH"/frontend -gitBasePath=$(git rev-parse --show-toplevel) -addedFiles=$(git diff --cached --name-only --diff-filter=d --line-prefix="${gitBasePath}"/) +get_changed_files() { + GIT_BASE_PATH=$(git rev-parse --show-toplevel) + path=$1 + git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" +} + +has_changed() { + files=$1 + echo "$files" | grep -q . +} + + + +frontend_files=$(get_changed_files "$FRONTEND_PATH") +backend_files=$(get_changed_files "$BACKEND_PATH") echo "*****Running prettier******" -cd "$gitBasePath"/frontend || exit -npm run esl-format-specific "$addedFiles" -npm run prettier-format "$addedFiles" +cd "$FRONTEND_PATH" || exit +has_changed "$frontend_files" && npm run prettier-format "$frontend_files" echo "*****Finish running prettier******" +echo "---------------------------------------------------------" + +echo "*****Running eslint******" +cd "$FRONTEND_PATH" || exit +has_changed "$frontend_files" && npm run esl-format-specific "$frontend_files" +echo "*****Finish running eslint******" + +echo "---------------------------------------------------------" + echo "*****Running maven formatter******" -cd "$gitBasePath" || exit -mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$addedFiles" +cd "$GIT_BASE_PATH" || exit +# shellcheck disable=SC2091 +has_changed "$backend_files" && mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$backend_files" echo "*****Finish running maven formatter******" +echo "---------------------------------------------------------" + echo "*****Adding changes to git******" -cd "$gitBasePath" || exit +cd "$GIT_BASE_PATH" || exit # shellcheck disable=SC2086 -git add $addedFiles +git add "$frontend_files" +git add "$backend_files" echo "*****Formatted files added again******" status=$? exit $status + From 974932ecfb6f08f7b494b95a3d8666ab6ffc9e61 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 08:47:20 +0100 Subject: [PATCH 39/78] clean up pre-commit hook --- frontend/scripts/pre-commit | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index f2894359e5..4e84883915 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -21,14 +21,14 @@ backend_files=$(get_changed_files "$BACKEND_PATH") echo "*****Running prettier******" cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run prettier-format "$frontend_files" +has_changed "$frontend_files" && npm run prettier-format "$frontend_files" || echo "No files found to format" echo "*****Finish running prettier******" echo "---------------------------------------------------------" echo "*****Running eslint******" cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run esl-format-specific "$frontend_files" +has_changed "$frontend_files" && npm run esl-format-specific "$frontend_files" || echo "No files found to format" echo "*****Finish running eslint******" echo "---------------------------------------------------------" @@ -36,7 +36,7 @@ echo "---------------------------------------------------------" echo "*****Running maven formatter******" cd "$GIT_BASE_PATH" || exit # shellcheck disable=SC2091 -has_changed "$backend_files" && mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$backend_files" +has_changed "$backend_files" && mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$backend_files" || echo "No files found to format" echo "*****Finish running maven formatter******" echo "---------------------------------------------------------" @@ -44,8 +44,8 @@ echo "---------------------------------------------------------" echo "*****Adding changes to git******" cd "$GIT_BASE_PATH" || exit # shellcheck disable=SC2086 -git add "$frontend_files" -git add "$backend_files" +has_changed "$frontend_files" && git add "$frontend_files" || echo "No frontend files changed, nothing to add" +has_changed "$backend_files" && git add "$backend_files" || echo "No backend_files files changed, nothing to add" echo "*****Formatted files added again******" status=$? From c14441ba8f06db8b72b4710b7be477306a874ee2 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 08:49:29 +0100 Subject: [PATCH 40/78] remove accidently added fiels --- .../java/ch/puzzle/okr/ForwardFilter.java | 11 +- .../java/ch/puzzle/okr/models/Objective.java | 123 ++++++------------ 2 files changed, 48 insertions(+), 86 deletions(-) diff --git a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java index c5c8368a11..2e517f4d59 100644 --- a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java +++ b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java @@ -1,13 +1,18 @@ package ch.puzzle.okr; -import java.io.IOException; -import jakarta.servlet.*; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import org.springframework.web.filter.GenericFilterBean; +import java.io.IOException; +import java.util.Arrays; + public class ForwardFilter extends GenericFilterBean { private static final Logger logger = LoggerFactory.getLogger(ForwardFilter.class); diff --git a/backend/src/main/java/ch/puzzle/okr/models/Objective.java b/backend/src/main/java/ch/puzzle/okr/models/Objective.java index 6d080d82f3..281c0d7353 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Objective.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Objective.java @@ -1,12 +1,14 @@ package ch.puzzle.okr.models; import jakarta.persistence.*; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import java.time.LocalDateTime; import java.util.Objects; @Entity -@Table(indexes = {@Index(name = "idx_objective_title", columnList = "title")}) +@Table(indexes = { @Index(name = "idx_objective_title", columnList = "title") }) public class Objective implements WriteableInterface { @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "sequence_objective") @@ -67,95 +69,51 @@ private Objective(Builder builder) { setModifiedBy(builder.modifiedBy); } - public Long getId() { - return id; - } + public Long getId() { return id; } - public int getVersion() { - return version; - } + public int getVersion() { return version; } - public String getTitle() { - return title; - } + public String getTitle() { return title; } - public void setTitle(String title) { - this.title = title; - } + public void setTitle(String title) { this.title = title; } - public User getCreatedBy() { - return createdBy; - } + public User getCreatedBy() { return createdBy; } - public void setCreatedBy(User createdBy) { - this.createdBy = createdBy; - } + public void setCreatedBy(User createdBy) { this.createdBy = createdBy; } - public Team getTeam() { - return team; - } + public Team getTeam() { return team; } - public void setTeam(Team team) { - this.team = team; - } + public void setTeam(Team team) { this.team = team; } - public Quarter getQuarter() { - return quarter; - } + public Quarter getQuarter() { return quarter; } - public void setQuarter(Quarter quarter) { - this.quarter = quarter; - } + public void setQuarter(Quarter quarter) { this.quarter = quarter; } - public String getDescription() { - return description; - } + public String getDescription() { return description; } - public void setDescription(String description) { - this.description = description; - } + public void setDescription(String description) { this.description = description; } - public LocalDateTime getModifiedOn() { - return modifiedOn; - } + public LocalDateTime getModifiedOn() { return modifiedOn; } - public void setModifiedOn(LocalDateTime modifiedOn) { - this.modifiedOn = modifiedOn; - } + public void setModifiedOn(LocalDateTime modifiedOn) { this.modifiedOn = modifiedOn; } - public State getState() { - return state; - } + public State getState() { return state; } - public void setState(State state) { - this.state = state; - } + public void setState(State state) { this.state = state; } - public LocalDateTime getCreatedOn() { - return createdOn; - } + public LocalDateTime getCreatedOn() { return createdOn; } - public void setCreatedOn(LocalDateTime createdOn) { - this.createdOn = createdOn; - } + public void setCreatedOn(LocalDateTime createdOn) { this.createdOn = createdOn; } - public User getModifiedBy() { - return modifiedBy; - } + public User getModifiedBy() { return modifiedBy; } - public void setModifiedBy(User modifiedBy) { - this.modifiedBy = modifiedBy; - } + public void setModifiedBy(User modifiedBy) { this.modifiedBy = modifiedBy; } @Override - public boolean isWriteable() { - return writeable; - } + public boolean isWriteable() { return writeable; } @Override - public void setWriteable(boolean writeable) { - this.writeable = writeable; - } + public void setWriteable(boolean writeable) { this.writeable = writeable; } @Override public String toString() { @@ -167,12 +125,10 @@ public String toString() { @Override public boolean equals(Object o) { - if (this == o) { + if (this == o) return true; - } - if (o == null || getClass() != o.getClass()) { + if (o == null || getClass() != o.getClass()) return false; - } Objective objective = (Objective) o; return Objects.equals(id, objective.id) && version == objective.version && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) @@ -184,17 +140,18 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, - version, - title, - createdBy, - team, - quarter, - description, - modifiedOn, - state, - createdOn, - modifiedBy); + return Objects + .hash(id, + version, + title, + createdBy, + team, + quarter, + description, + modifiedOn, + state, + createdOn, + modifiedBy); } public static final class Builder { From 83cd40058219490d6e09fe1fea9aa8578ee99724 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 08:53:17 +0100 Subject: [PATCH 41/78] remove objective from this pr From acfcfbcbfd84e2d68cd36402ffe24abe4cfcd3e1 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 09:00:42 +0100 Subject: [PATCH 42/78] add verbose option to git add in precommit hook --- frontend/scripts/pre-commit | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 4e84883915..b591158a6c 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -43,9 +43,9 @@ echo "---------------------------------------------------------" echo "*****Adding changes to git******" cd "$GIT_BASE_PATH" || exit -# shellcheck disable=SC2086 -has_changed "$frontend_files" && git add "$frontend_files" || echo "No frontend files changed, nothing to add" -has_changed "$backend_files" && git add "$backend_files" || echo "No backend_files files changed, nothing to add" +git status +has_changed "$frontend_files" && git add "$frontend_files" -v || echo "No frontend files changed, nothing to add" +has_changed "$backend_files" && git add "$backend_files" -v || echo "No backend_files files changed, nothing to add" echo "*****Formatted files added again******" status=$? From 9ab17c9263333430a93cdc2f44612973b0ad1516 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 09:01:23 +0100 Subject: [PATCH 43/78] remove objective model from pr From a66f0ffdd00444e51c65b4996e68a46840fd5a05 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 10:04:54 +0100 Subject: [PATCH 44/78] remove debug log --- frontend/scripts/pre-commit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index b591158a6c..7620e150bf 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -43,9 +43,9 @@ echo "---------------------------------------------------------" echo "*****Adding changes to git******" cd "$GIT_BASE_PATH" || exit -git status + has_changed "$frontend_files" && git add "$frontend_files" -v || echo "No frontend files changed, nothing to add" -has_changed "$backend_files" && git add "$backend_files" -v || echo "No backend_files files changed, nothing to add" +has_changed "$backend_files" && git add "$backend_files" -v || echo "No backend files files changed, nothing to add" echo "*****Formatted files added again******" status=$? From 6c79f0c5b3bc5332b7e8586dfe6d42ce0673faa6 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 10:08:30 +0100 Subject: [PATCH 45/78] restore objective model --- .../java/ch/puzzle/okr/models/Objective.java | 119 +++++++++++------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/backend/src/main/java/ch/puzzle/okr/models/Objective.java b/backend/src/main/java/ch/puzzle/okr/models/Objective.java index 281c0d7353..85a96b59dd 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Objective.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Objective.java @@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; + import java.time.LocalDateTime; import java.util.Objects; @@ -69,58 +70,102 @@ private Objective(Builder builder) { setModifiedBy(builder.modifiedBy); } - public Long getId() { return id; } + public Long getId() { + return id; + } - public int getVersion() { return version; } + public int getVersion() { + return version; + } - public String getTitle() { return title; } + public String getTitle() { + return title; + } - public void setTitle(String title) { this.title = title; } + public void setTitle(String title) { + this.title = title; + } - public User getCreatedBy() { return createdBy; } + public User getCreatedBy() { + return createdBy; + } - public void setCreatedBy(User createdBy) { this.createdBy = createdBy; } + public void setCreatedBy(User createdBy) { + this.createdBy = createdBy; + } - public Team getTeam() { return team; } + public Team getTeam() { + return team; + } - public void setTeam(Team team) { this.team = team; } + public void setTeam(Team team) { + this.team = team; + } - public Quarter getQuarter() { return quarter; } + public Quarter getQuarter() { + return quarter; + } - public void setQuarter(Quarter quarter) { this.quarter = quarter; } + public void setQuarter(Quarter quarter) { + this.quarter = quarter; + } - public String getDescription() { return description; } + public String getDescription() { + return description; + } - public void setDescription(String description) { this.description = description; } + public void setDescription(String description) { + this.description = description; + } - public LocalDateTime getModifiedOn() { return modifiedOn; } + public LocalDateTime getModifiedOn() { + return modifiedOn; + } - public void setModifiedOn(LocalDateTime modifiedOn) { this.modifiedOn = modifiedOn; } + public void setModifiedOn(LocalDateTime modifiedOn) { + this.modifiedOn = modifiedOn; + } - public State getState() { return state; } + public State getState() { + return state; + } - public void setState(State state) { this.state = state; } + public void setState(State state) { + this.state = state; + } - public LocalDateTime getCreatedOn() { return createdOn; } + public LocalDateTime getCreatedOn() { + return createdOn; + } - public void setCreatedOn(LocalDateTime createdOn) { this.createdOn = createdOn; } + public void setCreatedOn(LocalDateTime createdOn) { + this.createdOn = createdOn; + } - public User getModifiedBy() { return modifiedBy; } + public User getModifiedBy() { + return modifiedBy; + } - public void setModifiedBy(User modifiedBy) { this.modifiedBy = modifiedBy; } + public void setModifiedBy(User modifiedBy) { + this.modifiedBy = modifiedBy; + } @Override - public boolean isWriteable() { return writeable; } + public boolean isWriteable() { + return writeable; + } @Override - public void setWriteable(boolean writeable) { this.writeable = writeable; } + public void setWriteable(boolean writeable) { + this.writeable = writeable; + } @Override public String toString() { return "Objective{" + "id=" + id + ", version=" + version + ", title='" + title + '\'' + ", createdBy=" - + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' - + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" - + modifiedBy + ", writeable=" + writeable + '\'' + '}'; + + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' + + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" + + modifiedBy + ", writeable=" + writeable + '\'' + '}'; } @Override @@ -131,27 +176,17 @@ public boolean equals(Object o) { return false; Objective objective = (Objective) o; return Objects.equals(id, objective.id) && version == objective.version - && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) - && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) - && Objects.equals(description, objective.description) && Objects.equals(modifiedOn, objective.modifiedOn) - && state == objective.state && Objects.equals(createdOn, objective.createdOn) - && Objects.equals(modifiedBy, objective.modifiedBy); + && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) + && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) + && Objects.equals(description, objective.description) + && Objects.equals(modifiedOn, objective.modifiedOn) && state == objective.state + && Objects.equals(createdOn, objective.createdOn) && Objects.equals(modifiedBy, objective.modifiedBy); } @Override public int hashCode() { - return Objects - .hash(id, - version, - title, - createdBy, - team, - quarter, - description, - modifiedOn, - state, - createdOn, - modifiedBy); + return Objects.hash(id, version, title, createdBy, team, quarter, description, modifiedOn, state, createdOn, + modifiedBy); } public static final class Builder { From 73c99ceed6ea59fa9b6e2acb94fb1ac1a13814a9 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 13:07:21 +0100 Subject: [PATCH 46/78] add angular eslint config --- frontend/angular.json | 8 +- frontend/eslint.config.mjs | 116 ++- frontend/package-lock.json | 1664 ++++++++++++++++++++++++++++++++---- frontend/package.json | 8 +- 4 files changed, 1586 insertions(+), 210 deletions(-) diff --git a/frontend/angular.json b/frontend/angular.json index dd48ac3be5..cd63a81859 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -131,12 +131,18 @@ "devServerTarget": "frontend:serve:production" } } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] + } } } } }, "cli": { "analytics": false, - "schematicCollections": ["@cypress/schematic", "@schematics/angular"] + "schematicCollections": ["angular-eslint", "@cypress/schematic", "@schematics/angular"] } } diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index f62d12b602..dff38fe87c 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -3,51 +3,81 @@ import tsEslint from "typescript-eslint"; import unusedImports from "eslint-plugin-unused-imports"; import stylistic from "@stylistic/eslint-plugin"; import html from "@html-eslint/eslint-plugin"; +import angular from "angular-eslint"; export default tsEslint.config( - eslint.configs.recommended, ...tsEslint.configs.recommended, { - ...stylistic.configs["all-flat"], - files: ["**/*.ts"], - rules: { - "unused-imports/no-unused-imports": "error", - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-unused-expressions": "off", - "@typescript-eslint/ban-ts-comment": "off", - "no-undef": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "prefer-rest-params": "off", - //stylistic rules - "@stylistic/function-call-argument-newline": ["error", "never"], - "@stylistic/padded-blocks": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], - "@stylistic/indent": ["error", 2], - "@stylistic/quotes":["error","double"], - "@stylistic/multiline-ternary": ["off"], - }, - }, { - files: ["**/*.spec.ts"], - rules: { - "@typescript-eslint/no-explicit-any": "off", - "prefer-rest-params": "off", + { + extends: [ + eslint.configs.recommended, + ...tsEslint.configs.recommended, + ...tsEslint.configs.stylistic, + ...angular.configs.tsRecommended, + ...stylistic.configs["all-flat"] + ], + // processor: angular.processInlineTemplates, + files: ["**/*.ts"], + rules: { + "unused-imports/no-unused-imports": "error", + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-expressions": "off", + "@typescript-eslint/ban-ts-comment": "off", + "no-undef": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-namespace": "off", + "prefer-rest-params": "off", + //stylistic rules + "@stylistic/function-call-argument-newline": ["error", "never"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/newline-per-chained-call": ["error", {"ignoreChainWithDepth": 1}], + "@stylistic/indent": ["error", 2], + "@stylistic/quotes": ["error", "double"], + "@stylistic/multiline-ternary": ["off"], + "@angular-eslint/directive-selector": [ + "error", + { + type: "attribute", + prefix: "app", + style: "camelCase", + }, + ], + "@angular-eslint/component-selector": [ + "error", + { + type: "element", + prefix: "app", + style: "kebab-case", + } + ] + }, }, - }, { - ...html.configs["flat/recommended"], - files: ["**/*.html"], - rules: { - ...html.configs["flat/recommended"].rules, - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@html-eslint/require-img-alt": "off", - "@html-eslint/element-newline": "off", - //stylistic rules - "@html-eslint/indent": ["error",2], - } - }, { - plugins: { - "unused-imports": unusedImports, - "@stylistic": stylistic + { + files: ["**/*.spec.ts"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + "prefer-rest-params": "off", + }, + }, + { + files: ["**/*.html"], + extends: [ + ...html.configs["flat/recommended"], + ...angular.configs.templateRecommended, + ...angular.configs.templateAccessibility, + ], + rules: { + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@html-eslint/require-img-alt": "off", + "@html-eslint/element-newline": "off", + //stylistic rules + "@html-eslint/indent": ["error", 2], + } }, - } + { + plugins: { + "unused-imports": unusedImports, + "@stylistic": stylistic + }, + } ); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 53f2b44c02..e5ebfe6501 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,8 @@ "@angular/router": "^18.2.8", "@ngx-translate/core": "^16.0.0", "@ngx-translate/http-loader": "^16.0.0", + "@stylistic/eslint-plugin": "^2.11.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", "moment": "^2.30.1", @@ -34,16 +36,24 @@ "@angular/compiler-cli": "^18.2.8", "@cypress/schematic": "^2.5.2", "@cypress/skip-test": "^2.6.1", + "@eslint/js": "^9.15.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", + "@types/eslint__js": "^8.42.3", "@types/jest": "^29.5.13", "@types/uuid": "^10.0.0", + "angular-eslint": "19.0.2", "browserslist": "^4.24.2", "cypress": "^13.15.0", "cypress-real-events": "^1.13.0", + "eslint": "^9.16.0", + "eslint-plugin-unused-imports": "^4.1.4", "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.3.3", "typescript": "^5.5.4", + "typescript-eslint": "8.18.0", "uuid": "^11.0.0" }, "engines": { @@ -284,6 +294,305 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-eslint/builder": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", + "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/architect": { + "version": "0.1900.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.4.tgz", + "integrity": "sha512-9XwZ21BPYS2vGOOwVB40fsMyuwJT0H1lWaAMo8Umwi6XbKBVfaWbEhjtR9dlarrySKtFuTz9hmTZkIXHLjXPdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.0.4", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/core": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", + "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-eslint/builder/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular-eslint/builder/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", + "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", + "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", + "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2", + "aria-query": "5.3.2", + "axobject-query": "4.1.0" + }, + "peerDependencies": { + "@typescript-eslint/types": "^7.11.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/schematics": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-19.0.2.tgz", + "integrity": "sha512-wI4SyiAnUCrpigtK6PHRlVWMC9vWljqmlLhbsJV5O5yDajlmRdvgXvSHDefhJm0hSfvZYRXuiAARYv2+QVfnGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": ">= 19.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "ignore": "6.0.2", + "semver": "7.6.3", + "strip-json-comments": "3.1.1" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/core": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", + "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/schematics": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.4.tgz", + "integrity": "sha512-2r6Qs4N5NSPho+qzegCYS8kIgylXyH4DHaS7HJ5+4XvM1I8V8AII8payLWkUK0i29XufVoD5XfPUFnjxZrBfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.0.4", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.12", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/ignore": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", + "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular-eslint/template-parser": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", + "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "eslint-scope": "^8.0.2" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/template-parser/node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@angular-eslint/utils": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", + "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "19.0.2" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" + } + }, "node_modules/@angular/animations": { "version": "18.2.12", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.12.tgz", @@ -3154,24 +3463,278 @@ "win32" ], "engines": { - "node": ">=18" + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@html-eslint/eslint-plugin": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.27.0.tgz", + "integrity": "sha512-aAF14sgDKidMCCQpJ4kIhe+fwyAaAbvDlgVTIgd99F+HOWxokTTXDt39a3gewMBo76IeEHDaoizUDJQ/Vc7Mdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@html-eslint/parser": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@html-eslint/parser/-/parser-0.27.0.tgz", + "integrity": "sha512-F/A1M0jnDAYoRvJiiSC7pIBD9DAsf4EhbndbvEi81aozD/wI8WWXON50xZPUaGHCI1C+2syTVifxDz8MvDKaQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-html-parser": "^0.0.9" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@inquirer/checkbox": { @@ -4626,7 +5189,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -4640,7 +5202,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -4650,7 +5211,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -5334,6 +5894,25 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stylistic/eslint-plugin": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.0.tgz", + "integrity": "sha512-IvD2WXbOoSp0zNpyYbjdSyEjZtut78RYfj2WIlbChE7HFuposTK5X1hc5+4AyqYcjLXYdD5oo/sJtqMGFNRb1w==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.13.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=8.40.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -5481,6 +6060,27 @@ "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint__js": { + "version": "8.42.3", + "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", + "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -5608,7 +6208,6 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, "license": "MIT" }, "node_modules/@types/mime": { @@ -5792,6 +6391,202 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz", + "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/type-utils": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz", + "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==", + "license": "MITClause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz", + "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz", + "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz", + "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz", + "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz", + "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz", + "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.18.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", @@ -6030,10 +6825,9 @@ } }, "node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", - "dev": true, + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -6063,6 +6857,15 @@ "acorn": "^8" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", @@ -6167,17 +6970,131 @@ } } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/angular-eslint": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-19.0.2.tgz", + "integrity": "sha512-d8P/Y5+QXOOko1x5W3Pp/p4cr7arXKGHdMAv6jtrqHjsIrlBqZSZY18apKRdTysFjYuKa5G9M3hejtzwXXHNhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": ">= 19.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", + "@angular-eslint/builder": "19.0.2", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "@angular-eslint/schematics": "19.0.2", + "@angular-eslint/template-parser": "19.0.2", + "@typescript-eslint/types": "^8.0.0", + "@typescript-eslint/utils": "^8.0.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*", + "typescript-eslint": "^8.0.0" + } + }, + "node_modules/angular-eslint/node_modules/@angular-devkit/core": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", + "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/angular-eslint/node_modules/@angular-devkit/schematics": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.4.tgz", + "integrity": "sha512-2r6Qs4N5NSPho+qzegCYS8kIgylXyH4DHaS7HJ5+4XvM1I8V8AII8payLWkUK0i29XufVoD5XfPUFnjxZrBfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.0.4", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.12", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/angular-eslint/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/angular-eslint/node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/angular-eslint/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" }, - "peerDependencies": { - "ajv": "^8.8.2" + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/angular-oauth2-oidc": { @@ -6313,6 +7230,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -6429,6 +7356,16 @@ "dev": true, "license": "MIT" }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -6715,7 +7652,6 @@ "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/base64-js": { @@ -6898,7 +7834,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6909,7 +7844,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -7154,7 +8088,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7703,7 +8636,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/connect-history-api-fallback": { @@ -8060,10 +8992,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -8521,7 +9452,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -8557,6 +9487,12 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -9110,6 +10046,13 @@ "node": ">= 0.4" } }, + "node_modules/es-html-parser": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/es-html-parser/-/es-html-parser-0.0.9.tgz", + "integrity": "sha512-oniQMi+466VFsDzcdron9Ry/sqUJpDJg1bbDn0jFJKDdxXhwIOYDr4DgBnO5/yPLGj2xv+n5yy4L1Q0vAC5TYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", @@ -9157,101 +10100,377 @@ "@esbuild/win32-x64": "0.23.0" } }, - "node_modules/esbuild-wasm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.23.0.tgz", - "integrity": "sha512-6jP8UmWy6R6TUUV8bMuC3ZyZ6lZKI56x0tkxyCIqWwRRJ/DgeQKneh/Oid5EoGoPFLrGNkz47ZEtWAYuiY/u9g==", - "dev": true, + "node_modules/esbuild-wasm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.23.0.tgz", + "integrity": "sha512-6jP8UmWy6R6TUUV8bMuC3ZyZ6lZKI56x0tkxyCIqWwRRJ/DgeQKneh/Oid5EoGoPFLrGNkz47ZEtWAYuiY/u9g==", + "dev": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.5", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-unused-imports": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", + "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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==", + "license": "MIT" + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/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==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/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==", + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, + "node_modules/eslint/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==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/eslint/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==", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -9268,11 +10487,22 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -9285,7 +10515,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -9295,7 +10524,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -9542,14 +10770,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -9566,7 +10792,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -9579,7 +10804,12 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, "node_modules/fast-uri": { @@ -9593,7 +10823,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -9648,6 +10877,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -9685,7 +10926,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -9771,6 +11011,25 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -10054,7 +11313,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -10147,6 +11405,12 @@ "dev": true, "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "license": "MIT" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -10538,7 +11802,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -10608,7 +11871,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -10625,7 +11887,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -10668,7 +11929,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -10800,7 +12060,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10833,7 +12092,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -10912,7 +12170,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -11025,7 +12282,6 @@ "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/isobject": { @@ -13116,7 +14372,7 @@ "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -13236,6 +14492,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", @@ -13260,6 +14522,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -13336,6 +14604,15 @@ "source-map-support": "^0.5.5" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -13489,6 +14766,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/license-webpack-plugin": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", @@ -13704,6 +14994,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -14135,7 +15431,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -14155,7 +15450,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -14169,7 +15463,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -14269,7 +15562,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -14498,7 +15790,6 @@ "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/msgpackr": { @@ -14581,7 +15872,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, "license": "MIT" }, "node_modules/needle": { @@ -15117,6 +16407,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -15245,7 +16552,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -15383,7 +16689,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -15483,7 +16788,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -15503,7 +16807,6 @@ "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" @@ -15585,7 +16888,6 @@ "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" @@ -15880,20 +17182,13 @@ "dev": true, "license": "MIT" }, - "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "dev": true, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">= 0.8.0" } }, "node_modules/prettier": { @@ -16076,7 +17371,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -16126,7 +17420,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -16504,7 +17797,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -16634,7 +17926,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -16834,7 +18125,6 @@ "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" @@ -17049,7 +18339,6 @@ "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" @@ -17062,7 +18351,6 @@ "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" @@ -17596,7 +18884,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17967,7 +19254,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -18052,6 +19338,18 @@ "tree-kill": "cli.js" } }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", @@ -18142,6 +19440,18 @@ "dev": true, "license": "Unlicense" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -18190,7 +19500,6 @@ "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -18200,6 +19509,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.0.tgz", + "integrity": "sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.18.0", + "@typescript-eslint/parser": "8.18.0", + "@typescript-eslint/utils": "8.18.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -18355,7 +19687,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -19412,7 +20743,6 @@ "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" @@ -19431,6 +20761,15 @@ "dev": true, "license": "MIT" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -19665,7 +21004,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/frontend/package.json b/frontend/package.json index fedb161ffe..80cc8a6dd1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,8 @@ "prettier-check": "prettier --check \"./**/*.{json,css,scss,md,yaml,yml}\"", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", - "e2e": "ng e2e" + "e2e": "ng e2e", + "lint": "ng lint" }, "private": true, "dependencies": { @@ -60,17 +61,18 @@ "@types/eslint__js": "^8.42.3", "@types/jest": "^29.5.13", "@types/uuid": "^10.0.0", + "angular-eslint": "19.0.2", "browserslist": "^4.24.2", "cypress": "^13.15.0", "cypress-real-events": "^1.13.0", - "eslint": "^9.14.0", + "eslint": "^9.16.0", "eslint-plugin-unused-imports": "^4.1.4", "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.3.3", "typescript": "^5.5.4", - "typescript-eslint": "^8.15.0", + "typescript-eslint": "8.18.0", "uuid": "^11.0.0" }, "jest": { From 24ab36a5b35e2f40dba603fb3b693c2aeffc920e Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 13:32:31 +0100 Subject: [PATCH 47/78] clean up frontend formatter config --- frontend/eslint.config.mjs | 143 +++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index dff38fe87c..f1b76a26c1 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -4,80 +4,83 @@ import unusedImports from "eslint-plugin-unused-imports"; import stylistic from "@stylistic/eslint-plugin"; import html from "@html-eslint/eslint-plugin"; import angular from "angular-eslint"; +import angularTemplateParser from "@angular-eslint/template-parser"; export default tsEslint.config( - { - extends: [ - eslint.configs.recommended, - ...tsEslint.configs.recommended, - ...tsEslint.configs.stylistic, - ...angular.configs.tsRecommended, - ...stylistic.configs["all-flat"] - ], - // processor: angular.processInlineTemplates, - files: ["**/*.ts"], - rules: { - "unused-imports/no-unused-imports": "error", - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-unused-expressions": "off", - "@typescript-eslint/ban-ts-comment": "off", - "no-undef": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "prefer-rest-params": "off", - //stylistic rules - "@stylistic/function-call-argument-newline": ["error", "never"], - "@stylistic/padded-blocks": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", {"ignoreChainWithDepth": 1}], - "@stylistic/indent": ["error", 2], - "@stylistic/quotes": ["error", "double"], - "@stylistic/multiline-ternary": ["off"], - "@angular-eslint/directive-selector": [ - "error", - { - type: "attribute", - prefix: "app", - style: "camelCase", - }, - ], - "@angular-eslint/component-selector": [ - "error", - { - type: "element", - prefix: "app", - style: "kebab-case", - } - ] + { + files: ["**/*.ts"], + extends: [ + eslint.configs.recommended, + ...tsEslint.configs.recommended, + ...tsEslint.configs.stylistic, + ...angular.configs.tsRecommended, + ], + processor: angular.processInlineTemplates, + rules: { + ...stylistic.configs["all-flat"].rules, + "unused-imports/no-unused-imports": "error", + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-expressions": "off", + "@typescript-eslint/ban-ts-comment": "off", + "no-undef": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-namespace": "off", + "prefer-rest-params": "off", + //stylistic rules + "@stylistic/function-call-argument-newline": ["error", "never"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/newline-per-chained-call": ["error", { ignoreChainWithDepth: 1 }], + "@stylistic/indent": ["error", 2], + "@stylistic/quotes": ["error", "double"], + "@stylistic/multiline-ternary": ["off"], + "@angular-eslint/directive-selector": [ + "error", + { + type: "attribute", + prefix: "app", + style: "camelCase", }, - }, - { - files: ["**/*.spec.ts"], - rules: { - "@typescript-eslint/no-explicit-any": "off", - "prefer-rest-params": "off", + ], + "@angular-eslint/component-selector": [ + "error", + { + type: "element", + prefix: "app", + style: "kebab-case", }, + ], }, - { - files: ["**/*.html"], - extends: [ - ...html.configs["flat/recommended"], - ...angular.configs.templateRecommended, - ...angular.configs.templateAccessibility, - ], - rules: { - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@html-eslint/require-img-alt": "off", - "@html-eslint/element-newline": "off", - //stylistic rules - "@html-eslint/indent": ["error", 2], - } + }, + { + files: ["**/*.spec.ts"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + "prefer-rest-params": "off", }, - { - plugins: { - "unused-imports": unusedImports, - "@stylistic": stylistic - }, - } + }, + { + files: ["**/*.html"], + extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], + processor: angular.processInlineTemplates, + languageOptions: { + parser: angularTemplateParser, + }, + rules: { + ...html.configs.recommended.rules, + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@html-eslint/require-img-alt": "off", + "@html-eslint/element-newline": "off", + //stylistic rules + "@html-eslint/indent": ["error", 2], + }, + }, + { + plugins: { + "unused-imports": unusedImports, + "@stylistic": stylistic, + "@html-eslint": html, + }, + }, ); From 583736919ab64432cd8846a37fb40e93b89a0c17 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 14:28:41 +0100 Subject: [PATCH 48/78] add scss to eslint config --- frontend/eslint.config.mjs | 144 +++--- frontend/package-lock.json | 880 ++++++++++++++++++++++++++++++++++++- frontend/package.json | 2 + 3 files changed, 945 insertions(+), 81 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index f1b76a26c1..01063adeb0 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -5,82 +5,86 @@ import stylistic from "@stylistic/eslint-plugin"; import html from "@html-eslint/eslint-plugin"; import angular from "angular-eslint"; import angularTemplateParser from "@angular-eslint/template-parser"; +import scssConfig from "stylelint-config-standard-scss" export default tsEslint.config( - { - files: ["**/*.ts"], - extends: [ - eslint.configs.recommended, - ...tsEslint.configs.recommended, - ...tsEslint.configs.stylistic, - ...angular.configs.tsRecommended, - ], - processor: angular.processInlineTemplates, - rules: { - ...stylistic.configs["all-flat"].rules, - "unused-imports/no-unused-imports": "error", - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-unused-expressions": "off", - "@typescript-eslint/ban-ts-comment": "off", - "no-undef": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "prefer-rest-params": "off", - //stylistic rules - "@stylistic/function-call-argument-newline": ["error", "never"], - "@stylistic/padded-blocks": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", { ignoreChainWithDepth: 1 }], - "@stylistic/indent": ["error", 2], - "@stylistic/quotes": ["error", "double"], - "@stylistic/multiline-ternary": ["off"], - "@angular-eslint/directive-selector": [ - "error", - { - type: "attribute", - prefix: "app", - style: "camelCase", + { + files: ["**/*.ts"], + extends: [ + eslint.configs.recommended, + ...tsEslint.configs.recommended, + ...tsEslint.configs.stylistic, + ...angular.configs.tsRecommended, + ], + processor: angular.processInlineTemplates, + rules: { + ...stylistic.configs["all-flat"].rules, + "unused-imports/no-unused-imports": "error", + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-expressions": "off", + "@typescript-eslint/ban-ts-comment": "off", + "no-undef": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-namespace": "off", + "prefer-rest-params": "off", + //stylistic rules + "@stylistic/function-call-argument-newline": ["error", "never"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 1}], + "@stylistic/indent": ["error", 2], + "@stylistic/quotes": ["error", "double"], + "@stylistic/multiline-ternary": ["off"], + "@angular-eslint/directive-selector": [ + "error", + { + type: "attribute", + prefix: "app", + style: "camelCase", + }, + ], + "@angular-eslint/component-selector": [ + "error", + { + type: "element", + prefix: "app", + style: "kebab-case", + }, + ], }, - ], - "@angular-eslint/component-selector": [ - "error", - { - type: "element", - prefix: "app", - style: "kebab-case", - }, - ], }, - }, - { - files: ["**/*.spec.ts"], - rules: { - "@typescript-eslint/no-explicit-any": "off", - "prefer-rest-params": "off", + { + files: ["**/*.spec.ts"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + "prefer-rest-params": "off", + }, }, - }, - { - files: ["**/*.html"], - extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], - processor: angular.processInlineTemplates, - languageOptions: { - parser: angularTemplateParser, + { + ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === "0")) }, - rules: { - ...html.configs.recommended.rules, - // ToDo: Disable rules so eslint passes, fix in followup ticket - "@html-eslint/require-img-alt": "off", - "@html-eslint/element-newline": "off", - //stylistic rules - "@html-eslint/indent": ["error", 2], + { + files: ["**/*.html"], + extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], + processor: angular.processInlineTemplates, + languageOptions: { + parser: angularTemplateParser, + }, + rules: { + ...html.configs.recommended.rules, + // ToDo: Disable rules so eslint passes, fix in followup ticket + "@html-eslint/require-img-alt": "off", + "@html-eslint/element-newline": "off", + //stylistic rules + "@html-eslint/indent": ["error", 2], + }, }, - }, - { - plugins: { - "unused-imports": unusedImports, - "@stylistic": stylistic, - "@html-eslint": html, + { + plugins: { + "unused-imports": unusedImports, + "@stylistic": stylistic, + "@html-eslint": html, + }, }, - }, ); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e5ebfe6501..8dfbe30a39 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -52,6 +52,8 @@ "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.3.3", + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", "typescript-eslint": "8.18.0", "uuid": "^11.0.0" @@ -2949,6 +2951,76 @@ "node": ">=0.1.90" } }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, "node_modules/@cypress/request": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", @@ -3075,6 +3147,18 @@ "node": ">=14.17.0" } }, + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", @@ -7247,6 +7331,17 @@ "dev": true, "license": "MIT" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -8529,6 +8624,14 @@ "dev": true, "license": "MIT" }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -9005,6 +9108,17 @@ "node": ">= 8" } }, + "node_modules/css-functions-list": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", + "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12 || >=16" + } + }, "node_modules/css-loader": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", @@ -9058,6 +9172,20 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -9712,6 +9840,31 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -10819,6 +10972,17 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -11354,6 +11518,58 @@ "node": ">=10" } }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -11385,6 +11601,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -11583,6 +11807,20 @@ "dev": true, "license": "MIT" }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -14633,6 +14871,13 @@ "node": ">=6" } }, + "node_modules/known-css-properties": { + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", + "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", + "dev": true, + "license": "MIT" + }, "node_modules/launch-editor": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", @@ -15007,6 +15252,14 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -15380,6 +15633,25 @@ "tmpl": "1.0.5" } }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -15410,6 +15682,20 @@ "url": "https://github.com/sponsors/streamich" } }, + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -17161,6 +17447,68 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, "node_modules/postcss-selector-parser": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", @@ -18892,20 +19240,436 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/stylelint": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", + "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "license": "MIT", + "peer": true, "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2", + "@csstools/selector-specificity": "^5.0.0", + "@dual-bundle/import-meta-resolve": "^4.1.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.3", + "css-tree": "^3.0.1", + "debug": "^4.3.7", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^9.1.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^6.0.2", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.35.0", + "mathml-tag-names": "^2.1.3", + "meow": "^13.2.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.49", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "supports-hyperlinks": "^3.1.0", + "svg-tags": "^1.0.0", + "table": "^6.8.2", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", + "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.1", + "stylelint-scss": "^6.4.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.6.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-config-standard": { + "version": "36.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", + "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "stylelint-config-recommended": "^14.0.1" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-standard-scss": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-14.0.0.tgz", + "integrity": "sha512-6Pa26D9mHyi4LauJ83ls3ELqCglU6VfCXchovbEqQUiEkezvKdv6VgsIoMy58i00c854wVmOw0k8W5FTpuaVqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-standard": "^36.0.1" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.11.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-scss": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.10.0.tgz", + "integrity": "sha512-y03if6Qw9xBMoVaf7tzp5BbnYhYvudIKzURkhSHzcHG0bW0fAYvQpTUVJOe7DyhHaxeThBil4ObEMvGbV7+M+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.1", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.35.0", + "mdn-data": "^2.12.2", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.2" + } + }, + "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stylelint/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peer": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flat-cache": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flatted": "^3.3.1", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", + "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "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", + "peer": true, + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylelint/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stylelint/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-hyperlinks/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", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/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", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", @@ -18918,6 +19682,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true, + "peer": true + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -18935,6 +19706,93 @@ "dev": true, "license": "MIT" }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/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", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/table/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", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/table/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", + "peer": true + }, + "node_modules/table/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", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 80cc8a6dd1..f54b2b7392 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -71,6 +71,8 @@ "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.3.3", + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", "typescript-eslint": "8.18.0", "uuid": "^11.0.0" From f3322bbe53e602ccfbab0c49631e2e3974fd5075 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 14:32:58 +0100 Subject: [PATCH 49/78] rename npm scripts --- frontend/package.json | 13 ++++++------- frontend/scripts/pre-commit | 2 +- .../action-plan/action-plan.component.scss | 8 ++++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index f54b2b7392..dd0c0f30ca 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,17 +13,16 @@ "cypress:run": "cypress run --browser chrome", "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "npm run esl-format && npm run prettier-format", - "check": "npm run es-check && npm run prettier-check", - "esl-format-specific": "eslint --fix ", - "esl-format": "eslint --fix .", - "es-check": "eslint .", + "format": "npm run lint:format && npm run prettier-format", + "check": "npm run lint && npm run prettier-check", + "lint:format:specific": "eslint --fix ", + "lint:format": "eslint --fix .", + "lint": "eslint .", "prettier-format": "prettier --write \"./**/*.{json,css,scss,md,yaml,yml}\"", "prettier-check": "prettier --check \"./**/*.{json,css,scss,md,yaml,yml}\"", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", - "e2e": "ng e2e", - "lint": "ng lint" + "e2e": "ng e2e" }, "private": true, "dependencies": { diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 7620e150bf..86590b66be 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -28,7 +28,7 @@ echo "---------------------------------------------------------" echo "*****Running eslint******" cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run esl-format-specific "$frontend_files" || echo "No files found to format" +has_changed "$frontend_files" && npm run lint:format:specific "$frontend_files" || echo "No files found to format" echo "*****Finish running eslint******" echo "---------------------------------------------------------" diff --git a/frontend/src/app/components/action-plan/action-plan.component.scss b/frontend/src/app/components/action-plan/action-plan.component.scss index ce0966283e..6f5232bd9a 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.scss +++ b/frontend/src/app/components/action-plan/action-plan.component.scss @@ -7,14 +7,18 @@ height: 32px; } -.cdk-drag-preview { +.cdk-drag-preview + + +{ box-sizing: border-box; border-radius: 4px; box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12); -} + + } .cdk-drag-placeholder { opacity: 0; From 889a8ac402f4f9a6b0d3b44a6d341aac485b7ece Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Tue, 10 Dec 2024 15:14:33 +0100 Subject: [PATCH 50/78] use json eslint plugin and remove prettier --- frontend/README.md | 4 +- frontend/eslint.config.mjs | 10 ++ frontend/package-lock.json | 208 ++++++++++++++++++++++++++++++++---- frontend/package.json | 8 +- frontend/scripts/pre-commit | 7 -- 5 files changed, 205 insertions(+), 32 deletions(-) diff --git a/frontend/README.md b/frontend/README.md index 57be403a17..d08b490966 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -30,8 +30,8 @@ Build: ## Formatting -We use the **prettier** code formatter for the frontend code: -https://www.npmjs.com/package/prettier +We use the **EsLint** code formatter for the frontend code: +https://eslint.org/ ## Test Coverage diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 01063adeb0..2100be05c8 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -6,6 +6,8 @@ import html from "@html-eslint/eslint-plugin"; import angular from "angular-eslint"; import angularTemplateParser from "@angular-eslint/template-parser"; import scssConfig from "stylelint-config-standard-scss" +import jsonConfig from "eslint-plugin-i18n-json" + export default tsEslint.config( { @@ -80,11 +82,19 @@ export default tsEslint.config( "@html-eslint/indent": ["error", 2], }, }, + { + files: ["**/*.json"], + processor: jsonConfig.processors[".json"], + rules: { + ...jsonConfig.configs.recommended.rules + } + }, { plugins: { "unused-imports": unusedImports, "@stylistic": stylistic, "@html-eslint": html, + "i18n-json": jsonConfig }, }, ); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8dfbe30a39..598dea2e7c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,6 +25,7 @@ "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", + "eslint-plugin-i18n-json": "^4.0.0", "moment": "^2.30.1", "ngx-toastr": "^19.0.0", "rxjs": "^7.8.1", @@ -953,7 +954,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz", "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/highlight": "^7.25.9", @@ -1368,7 +1368,6 @@ "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" @@ -1417,7 +1416,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -3737,6 +3735,57 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.1.tgz", + "integrity": "sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.5", + "@formatjs/intl-localematcher": "0.5.9", + "decimal.js": "10", + "tslib": "2" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.5.tgz", + "integrity": "sha512-6PoewUMrrcqxSoBXAOJDiW1m+AmkrAj0RiXnOMD59GRaswjXhm3MDhgepXPBgonc09oSirAJTsAggzAGQf6A6g==", + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.7.tgz", + "integrity": "sha512-cuEHyRM5VqLQobANOjtjlgU7+qmk9Q3fDQuBiRRJ3+Wp3ZoZhpUPtUfuimZXsir6SaI2TaAJ+SLo9vLnV5QcbA==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.1", + "@formatjs/icu-skeleton-parser": "1.8.11", + "tslib": "2" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.11.tgz", + "integrity": "sha512-8LlHHE/yL/zVJZHAX3pbKaCjZKmBIO6aJY1mkVh4RMSEu/2WRZ4Ysvv3kKXJ9M8RJLBHdnk1/dUQFdod1Dt7Dw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.1", + "tslib": "2" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.9.tgz", + "integrity": "sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA==", + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, "node_modules/@html-eslint/eslint-plugin": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.27.0.tgz", @@ -7247,7 +7296,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -8230,7 +8278,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -8611,7 +8658,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -8621,7 +8667,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "license": "MIT" }, "node_modules/colord": { @@ -9597,7 +9642,6 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true, "license": "MIT" }, "node_modules/dedent": { @@ -9830,6 +9874,15 @@ "dev": true, "license": "MIT" }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -10170,7 +10223,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -10287,7 +10339,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -10385,6 +10436,90 @@ } } }, + "node_modules/eslint-plugin-i18n-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-i18n-json/-/eslint-plugin-i18n-json-4.0.0.tgz", + "integrity": "sha512-rglbr9f/UaPN/OeiSLVVFlIh4RrXPTzX5qr4tqOdTj1Ryr8xIhUzriDDuyuPWliektO86c/zy1RldmBIOfDNsQ==", + "license": "MIT", + "dependencies": { + "@formatjs/icu-messageformat-parser": "^2.0.18", + "chalk": "^2.3.2", + "indent-string": "^3.2.0", + "jest-diff": "^22.0.3", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "lodash.isplainobject": "^4.0.6", + "lodash.set": "^4.3.2", + "log-symbols": "^2.2.0", + "parse-json": "^5.2.0", + "plur": "^2.1.2", + "pretty-format": "^22.0.3" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=4.0.0" + } + }, + "node_modules/eslint-plugin-i18n-json/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-i18n-json/node_modules/indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-i18n-json/node_modules/jest-diff": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", + "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1", + "diff": "^3.2.0", + "jest-get-type": "^22.4.3", + "pretty-format": "^22.4.3" + } + }, + "node_modules/eslint-plugin-i18n-json/node_modules/jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "license": "MIT" + }, + "node_modules/eslint-plugin-i18n-json/node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-i18n-json/node_modules/pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + } + }, "node_modules/eslint-plugin-unused-imports": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", @@ -11646,7 +11781,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -12242,11 +12376,19 @@ "node": ">= 10" } }, + "node_modules/irregular-plurals": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", + "integrity": "sha512-kniTIJmaZYiwa17eTtWIfm0K342seyugl6vuC8DiiyiRAJWAVlLkqGCI0Im0neo0TkXw+pRcKaBPRdcKHnQJ6Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, "license": "MIT" }, "node_modules/is-binary-path": { @@ -14620,7 +14762,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -15046,7 +15187,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/listr2": { @@ -15232,6 +15372,24 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -15252,6 +15410,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", + "license": "MIT" + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -16987,7 +17151,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -17006,7 +17169,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, "license": "MIT" }, "node_modules/parse-node-version": { @@ -17167,7 +17329,6 @@ "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": { @@ -17316,6 +17477,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha512-WhcHk576xg9y/iv6RWOuroZgsqvCbJN+XGvAypCJwLAYs2iWDp5LUmvaCdV6JR2O0SMBf8l6p7A94AyLCFVMlQ==", + "license": "MIT", + "dependencies": { + "irregular-plurals": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss": { "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", @@ -19617,7 +19790,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" diff --git a/frontend/package.json b/frontend/package.json index dd0c0f30ca..53791be630 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,13 +13,11 @@ "cypress:run": "cypress run --browser chrome", "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "npm run lint:format && npm run prettier-format", - "check": "npm run lint && npm run prettier-check", + "format": "npm run lint:format", + "check": "npm run lint", "lint:format:specific": "eslint --fix ", "lint:format": "eslint --fix .", "lint": "eslint .", - "prettier-format": "prettier --write \"./**/*.{json,css,scss,md,yaml,yml}\"", - "prettier-check": "prettier --check \"./**/*.{json,css,scss,md,yaml,yml}\"", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", "e2e": "ng e2e" @@ -43,6 +41,7 @@ "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", + "eslint-plugin-i18n-json": "^4.0.0", "moment": "^2.30.1", "ngx-toastr": "^19.0.0", "rxjs": "^7.8.1", @@ -69,7 +68,6 @@ "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", - "prettier": "^3.3.3", "stylelint-config-recommended-scss": "^14.1.0", "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 86590b66be..6a1662a35e 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -19,13 +19,6 @@ has_changed() { frontend_files=$(get_changed_files "$FRONTEND_PATH") backend_files=$(get_changed_files "$BACKEND_PATH") -echo "*****Running prettier******" -cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run prettier-format "$frontend_files" || echo "No files found to format" -echo "*****Finish running prettier******" - -echo "---------------------------------------------------------" - echo "*****Running eslint******" cd "$FRONTEND_PATH" || exit has_changed "$frontend_files" && npm run lint:format:specific "$frontend_files" || echo "No files found to format" From e630a67c4242b5faf965bf0aa007f7a82661e3d6 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 09:12:35 +0100 Subject: [PATCH 51/78] use prettier again to format scss --- frontend/eslint.config.mjs | 15 +++++---------- frontend/package.json | 2 ++ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 2100be05c8..a09aba73f6 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -6,7 +6,6 @@ import html from "@html-eslint/eslint-plugin"; import angular from "angular-eslint"; import angularTemplateParser from "@angular-eslint/template-parser"; import scssConfig from "stylelint-config-standard-scss" -import jsonConfig from "eslint-plugin-i18n-json" export default tsEslint.config( @@ -38,6 +37,7 @@ export default tsEslint.config( "@stylistic/indent": ["error", 2], "@stylistic/quotes": ["error", "double"], "@stylistic/multiline-ternary": ["off"], + "@stylistic/object-curly-spacing": ["error", "always"], "@angular-eslint/directive-selector": [ "error", { @@ -63,9 +63,6 @@ export default tsEslint.config( "prefer-rest-params": "off", }, }, - { - ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === "0")) - }, { files: ["**/*.html"], extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], @@ -83,18 +80,16 @@ export default tsEslint.config( }, }, { - files: ["**/*.json"], - processor: jsonConfig.processors[".json"], - rules: { - ...jsonConfig.configs.recommended.rules - } + // files: ["**/*.scss"], + ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === "0")) }, + + { plugins: { "unused-imports": unusedImports, "@stylistic": stylistic, "@html-eslint": html, - "i18n-json": jsonConfig }, }, ); diff --git a/frontend/package.json b/frontend/package.json index 53791be630..ecd669adc5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,6 +18,7 @@ "lint:format:specific": "eslint --fix ", "lint:format": "eslint --fix .", "lint": "eslint .", + "prettier:lint": "prettier --check .", "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", "e2e": "ng e2e" @@ -68,6 +69,7 @@ "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", + "prettier": "^3.4.2", "stylelint-config-recommended-scss": "^14.1.0", "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", From 6c5de0dbd6b7fbf8f41017cdca80835e40a1bc42 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 10:44:08 +0100 Subject: [PATCH 52/78] add prettierignore file --- frontend/.prettierignore | 5 +- frontend/.prettierrc | 6 + frontend/.prettierrc.json | 1 - frontend/README.md | 20 +-- frontend/angular.json | 280 ++++++++++++++++++------------------- frontend/cypress.config.ts | 24 ++-- frontend/eslint.config.mjs | 100 +++++++------ frontend/package.json | 176 +++++++++++------------ frontend/setup-jest.ts | 2 +- 9 files changed, 309 insertions(+), 305 deletions(-) create mode 100644 frontend/.prettierrc delete mode 100644 frontend/.prettierrc.json diff --git a/frontend/.prettierignore b/frontend/.prettierignore index df28f831e6..dae0d5dff3 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,3 +1,2 @@ -src/assets/ -dist/ -.angular/ +!**/*.json +!**/*.css diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 0000000000..e74ed9ff35 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": false, + "singleQuote": true +} diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/frontend/.prettierrc.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/frontend/README.md b/frontend/README.md index d08b490966..d6bf4073eb 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -44,16 +44,16 @@ Open the html file in browser and you get a beautiful overview ## Cypress Tests - local setup - - start local Docker `docker-compose up` - - start local Server: `OkrApplication-E2E` - - start local Client: `npm run start` + - start local Docker `docker-compose up` + - start local Server: `OkrApplication-E2E` + - start local Client: `npm run start` - run selected Tests - - npm run `npm run cypress:open` - - in Cypress App, select `E2E Testing` and `Chrome` as Browser + - npm run `npm run cypress:open` + - in Cypress App, select `E2E Testing` and `Chrome` as Browser - run all tests - - npm run `npm run cypress:run` - - in Cypress App, select `E2E Testing` and `Chrome` as Browser + - npm run `npm run cypress:run` + - in Cypress App, select `E2E Testing` and `Chrome` as Browser - in case of failing Tests: - - stop and restart local Server - - stop and restart local Client - - re-run Cypress Tests + - stop and restart local Server + - stop and restart local Client + - re-run Cypress Tests diff --git a/frontend/angular.json b/frontend/angular.json index cd63a81859..61e3cd382f 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -1,148 +1,148 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "frontend": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist/frontend", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "zone.js", - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": ["src/favicon.ico", "src/assets"], - "styles": [ - "node_modules/bootstrap/dist/css/bootstrap.min.css", - "node_modules/@angular/material/prebuilt-themes/indigo-pink.css", - "node_modules/ngx-toastr/toastr.css", - "src/style/styles.scss" - ], - "stylePreprocessorOptions": { - "includePaths": ["src/style", "src/assets"] + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "frontend": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } }, - "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "3mb", - "maximumError": "5mb" + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/frontend", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "zone.js", + "tsConfig": "tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": ["src/favicon.ico", "src/assets"], + "styles": [ + "node_modules/bootstrap/dist/css/bootstrap.min.css", + "node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "node_modules/ngx-toastr/toastr.css", + "src/style/styles.scss" + ], + "stylePreprocessorOptions": { + "includePaths": ["src/style", "src/assets"] + }, + "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "3mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "300kb", + "maximumError": "400kb" + } + ], + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" }, - { - "type": "anyComponentStyle", - "maximumWarning": "300kb", - "maximumError": "400kb" - } - ], - "fileReplacements": [ - { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "frontend:build:production" + }, + "development": { + "proxyConfig": "src/proxy.conf.json", + "buildTarget": "frontend:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "frontend:build" + } + }, + "cypress-run": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve" + }, + "configurations": { + "production": { + "devServerTarget": "frontend:serve:production" + } + } + }, + "cypress-open": { + "builder": "@cypress/schematic:cypress", + "options": { + "watch": true, + "headless": false + } + }, + "ct": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve", + "watch": true, + "headless": false, + "testingType": "component" + }, + "configurations": { + "development": { + "devServerTarget": "frontend:serve:development" + } + } + }, + "e2e": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve", + "watch": true, + "headless": false + }, + "configurations": { + "production": { + "devServerTarget": "frontend:serve:production" + } + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] + } } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "frontend:build:production" - }, - "development": { - "proxyConfig": "src/proxy.conf.json", - "buildTarget": "frontend:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "frontend:build" - } - }, - "cypress-run": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve" - }, - "configurations": { - "production": { - "devServerTarget": "frontend:serve:production" - } - } - }, - "cypress-open": { - "builder": "@cypress/schematic:cypress", - "options": { - "watch": true, - "headless": false - } - }, - "ct": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve", - "watch": true, - "headless": false, - "testingType": "component" - }, - "configurations": { - "development": { - "devServerTarget": "frontend:serve:development" - } - } - }, - "e2e": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve", - "watch": true, - "headless": false - }, - "configurations": { - "production": { - "devServerTarget": "frontend:serve:production" } - } - }, - "lint": { - "builder": "@angular-eslint/builder:lint", - "options": { - "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] - } } - } + }, + "cli": { + "analytics": false, + "schematicCollections": ["angular-eslint", "@cypress/schematic", "@schematics/angular"] } - }, - "cli": { - "analytics": false, - "schematicCollections": ["angular-eslint", "@cypress/schematic", "@schematics/angular"] - } } diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts index b188ef99ec..15426169ed 100644 --- a/frontend/cypress.config.ts +++ b/frontend/cypress.config.ts @@ -1,14 +1,14 @@ -import { defineConfig } from 'cypress'; +import { defineConfig } from 'cypress' export default defineConfig({ - e2e: { - baseUrl: 'http://pitc.okr.localhost:4200', - experimentalMemoryManagement: true, - testIsolation: true, - viewportWidth: 1920, - viewportHeight: 1080, - }, - env: { - login_url: 'http://localhost:8544', - }, -}); + e2e: { + baseUrl: 'http://pitc.okr.localhost:4200', + experimentalMemoryManagement: true, + testIsolation: true, + viewportWidth: 1920, + viewportHeight: 1080, + }, + env: { + login_url: 'http://localhost:8544', + }, +}) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index a09aba73f6..37ca0a0b51 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,16 +1,15 @@ -import eslint from "@eslint/js"; -import tsEslint from "typescript-eslint"; -import unusedImports from "eslint-plugin-unused-imports"; -import stylistic from "@stylistic/eslint-plugin"; -import html from "@html-eslint/eslint-plugin"; -import angular from "angular-eslint"; -import angularTemplateParser from "@angular-eslint/template-parser"; -import scssConfig from "stylelint-config-standard-scss" - +import eslint from '@eslint/js' +import tsEslint from 'typescript-eslint' +import unusedImports from 'eslint-plugin-unused-imports' +import stylistic from '@stylistic/eslint-plugin' +import html from '@html-eslint/eslint-plugin' +import angular from 'angular-eslint' +import angularTemplateParser from '@angular-eslint/template-parser' +import scssConfig from 'stylelint-config-standard-scss' export default tsEslint.config( { - files: ["**/*.ts"], + files: ['**/*.ts'], extends: [ eslint.configs.recommended, ...tsEslint.configs.recommended, @@ -19,52 +18,52 @@ export default tsEslint.config( ], processor: angular.processInlineTemplates, rules: { - ...stylistic.configs["all-flat"].rules, - "unused-imports/no-unused-imports": "error", + ...stylistic.configs['all-flat'].rules, + 'unused-imports/no-unused-imports': 'error', // ToDo: Disable rules so eslint passes, fix in followup ticket - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-unused-expressions": "off", - "@typescript-eslint/ban-ts-comment": "off", - "no-undef": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "prefer-rest-params": "off", + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + 'no-undef': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-namespace': 'off', + 'prefer-rest-params': 'off', //stylistic rules - "@stylistic/function-call-argument-newline": ["error", "never"], - "@stylistic/padded-blocks": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 1}], - "@stylistic/indent": ["error", 2], - "@stylistic/quotes": ["error", "double"], - "@stylistic/multiline-ternary": ["off"], - "@stylistic/object-curly-spacing": ["error", "always"], - "@angular-eslint/directive-selector": [ - "error", + '@stylistic/function-call-argument-newline': ['error', 'never'], + '@stylistic/padded-blocks': ['error', 'never'], + '@stylistic/dot-location': ['error', 'property'], + '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }], + '@stylistic/indent': ['error', 2], + '@stylistic/quotes': ['error', 'double'], + '@stylistic/multiline-ternary': ['off'], + '@stylistic/object-curly-spacing': ['error', 'always'], + '@angular-eslint/directive-selector': [ + 'error', { - type: "attribute", - prefix: "app", - style: "camelCase", + type: 'attribute', + prefix: 'app', + style: 'camelCase', }, ], - "@angular-eslint/component-selector": [ - "error", + '@angular-eslint/component-selector': [ + 'error', { - type: "element", - prefix: "app", - style: "kebab-case", + type: 'element', + prefix: 'app', + style: 'kebab-case', }, ], }, }, { - files: ["**/*.spec.ts"], + files: ['**/*.spec.ts'], rules: { - "@typescript-eslint/no-explicit-any": "off", - "prefer-rest-params": "off", + '@typescript-eslint/no-explicit-any': 'off', + 'prefer-rest-params': 'off', }, }, { - files: ["**/*.html"], + files: ['**/*.html'], extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], processor: angular.processInlineTemplates, languageOptions: { @@ -73,23 +72,22 @@ export default tsEslint.config( rules: { ...html.configs.recommended.rules, // ToDo: Disable rules so eslint passes, fix in followup ticket - "@html-eslint/require-img-alt": "off", - "@html-eslint/element-newline": "off", + '@html-eslint/require-img-alt': 'off', + '@html-eslint/element-newline': 'off', //stylistic rules - "@html-eslint/indent": ["error", 2], + '@html-eslint/indent': ['error', 2], }, }, { // files: ["**/*.scss"], - ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === "0")) + ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === '0')), }, - { plugins: { - "unused-imports": unusedImports, - "@stylistic": stylistic, - "@html-eslint": html, + 'unused-imports': unusedImports, + '@stylistic': stylistic, + '@html-eslint': html, }, - }, -); + } +) diff --git a/frontend/package.json b/frontend/package.json index ecd669adc5..2fafd00da1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,89 +1,91 @@ { - "name": "frontend", - "version": "2.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "build:staging": "ng build --configuration staging", - "watch": "ng build --watch --configuration development", - "watch:prod": "ng build --watch", - "test": "jest --silent", - "cypress:open": "cypress open", - "cypress:run": "cypress run --browser chrome", - "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", - "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "format": "npm run lint:format", - "check": "npm run lint", - "lint:format:specific": "eslint --fix ", - "lint:format": "eslint --fix .", - "lint": "eslint .", - "prettier:lint": "prettier --check .", - "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", - "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", - "e2e": "ng e2e" - }, - "private": true, - "dependencies": { - "@angular/animations": "^18.2.8", - "@angular/cdk": "^18.2.9", - "@angular/common": "^18.2.8", - "@angular/compiler": "^18.2.8", - "@angular/core": "^18.2.8", - "@angular/forms": "^18.2.8", - "@angular/material": "^18.2.9", - "@angular/material-moment-adapter": "^18.2.9", - "@angular/platform-browser": "^18.2.8", - "@angular/platform-browser-dynamic": "^18.2.8", - "@angular/router": "^18.2.8", - "@ngx-translate/core": "^16.0.0", - "@ngx-translate/http-loader": "^16.0.0", - "@stylistic/eslint-plugin": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "angular-oauth2-oidc": "^17.0.2", - "bootstrap": "^5.3.3", - "eslint-plugin-i18n-json": "^4.0.0", - "moment": "^2.30.1", - "ngx-toastr": "^19.0.0", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^18.2.9", - "@angular/cli": "~18.2.9", - "@angular/compiler-cli": "^18.2.8", - "@cypress/schematic": "^2.5.2", - "@cypress/skip-test": "^2.6.1", - "@eslint/js": "^9.15.0", - "@html-eslint/eslint-plugin": "^0.27.0", - "@html-eslint/parser": "^0.27.0", - "@types/eslint__js": "^8.42.3", - "@types/jest": "^29.5.13", - "@types/uuid": "^10.0.0", - "angular-eslint": "19.0.2", - "browserslist": "^4.24.2", - "cypress": "^13.15.0", - "cypress-real-events": "^1.13.0", - "eslint": "^9.16.0", - "eslint-plugin-unused-imports": "^4.1.4", - "jest": "^29.7.0", - "jest-preset-angular": "^14.2.4", - "ngx-translate-testing": "^7.0.0", - "prettier": "^3.4.2", - "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-config-standard-scss": "^14.0.0", - "typescript": "^5.5.4", - "typescript-eslint": "8.18.0", - "uuid": "^11.0.0" - }, - "jest": { - "preset": "jest-preset-angular", - "setupFilesAfterEnv": [ - "/setup-jest.ts" - ] - }, - "engines": { - "npm": ">=10.0.0 <12.0.0", - "node": ">=22.0.0 <23.0.0" - } + "name": "frontend", + "version": "2.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "build:staging": "ng build --configuration staging", + "watch": "ng build --watch --configuration development", + "watch:prod": "ng build --watch", + "test": "jest --silent", + "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", + "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", + "cypress:open": "cypress open", + "cypress:run": "cypress run --browser chrome", + "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", + "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", + "e2e": "ng e2e", + "format": "npm run lint:format", + "check": "npm run lint", + "lint:format:specific": "eslint --fix ", + "lint:format": "eslint --fix .", + "lint": "eslint .", + "prettier:lint:format:specific": "prettier --write", + "prettier:lint:format": "prettier --write .", + "prettier:lint": "prettier --check ." + }, + "private": true, + "dependencies": { + "@angular/animations": "^18.2.8", + "@angular/cdk": "^18.2.9", + "@angular/common": "^18.2.8", + "@angular/compiler": "^18.2.8", + "@angular/core": "^18.2.8", + "@angular/forms": "^18.2.8", + "@angular/material": "^18.2.9", + "@angular/material-moment-adapter": "^18.2.9", + "@angular/platform-browser": "^18.2.8", + "@angular/platform-browser-dynamic": "^18.2.8", + "@angular/router": "^18.2.8", + "@ngx-translate/core": "^16.0.0", + "@ngx-translate/http-loader": "^16.0.0", + "@stylistic/eslint-plugin": "^2.11.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "angular-oauth2-oidc": "^17.0.2", + "bootstrap": "^5.3.3", + "eslint-plugin-i18n-json": "^4.0.0", + "moment": "^2.30.1", + "ngx-toastr": "^19.0.0", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^18.2.9", + "@angular/cli": "~18.2.9", + "@angular/compiler-cli": "^18.2.8", + "@cypress/schematic": "^2.5.2", + "@cypress/skip-test": "^2.6.1", + "@eslint/js": "^9.15.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", + "@types/eslint__js": "^8.42.3", + "@types/jest": "^29.5.13", + "@types/uuid": "^10.0.0", + "angular-eslint": "19.0.2", + "browserslist": "^4.24.2", + "cypress": "^13.15.0", + "cypress-real-events": "^1.13.0", + "eslint": "^9.16.0", + "eslint-plugin-unused-imports": "^4.1.4", + "jest": "^29.7.0", + "jest-preset-angular": "^14.2.4", + "ngx-translate-testing": "^7.0.0", + "prettier": "^3.4.2", + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-standard-scss": "^14.0.0", + "typescript": "^5.5.4", + "typescript-eslint": "8.18.0", + "uuid": "^11.0.0" + }, + "jest": { + "preset": "jest-preset-angular", + "setupFilesAfterEnv": [ + "/setup-jest.ts" + ] + }, + "engines": { + "npm": ">=10.0.0 <12.0.0", + "node": ">=22.0.0 <23.0.0" + } } diff --git a/frontend/setup-jest.ts b/frontend/setup-jest.ts index 1100b3e8a6..90bc5062ea 100644 --- a/frontend/setup-jest.ts +++ b/frontend/setup-jest.ts @@ -1 +1 @@ -import 'jest-preset-angular/setup-jest'; +import 'jest-preset-angular/setup-jest' From 80a9435e15f351eb5c398f371391dd19c6f2bf06 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 10:52:12 +0100 Subject: [PATCH 53/78] configure prettier --- frontend/.prettierignore | 4 +- frontend/.prettierrc | 10 +- frontend/angular.json | 280 +++++++++++++++++++-------------------- frontend/package.json | 178 ++++++++++++------------- 4 files changed, 240 insertions(+), 232 deletions(-) diff --git a/frontend/.prettierignore b/frontend/.prettierignore index dae0d5dff3..5f3d5e8993 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,2 +1,2 @@ -!**/*.json -!**/*.css +**/*.html +**/*.ts diff --git a/frontend/.prettierrc b/frontend/.prettierrc index e74ed9ff35..b64bb3eae5 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -2,5 +2,13 @@ "trailingComma": "es5", "tabWidth": 4, "semi": false, - "singleQuote": true + "singleQuote": true, + "overrides": [ + { + "files": "**/*.json", + "options": { + "tabWidth": 2 + } + } + ] } diff --git a/frontend/angular.json b/frontend/angular.json index 61e3cd382f..cd63a81859 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -1,148 +1,148 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "frontend": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "frontend": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/frontend", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "zone.js", + "tsConfig": "tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": ["src/favicon.ico", "src/assets"], + "styles": [ + "node_modules/bootstrap/dist/css/bootstrap.min.css", + "node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "node_modules/ngx-toastr/toastr.css", + "src/style/styles.scss" + ], + "stylePreprocessorOptions": { + "includePaths": ["src/style", "src/assets"] }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist/frontend", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "zone.js", - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": ["src/favicon.ico", "src/assets"], - "styles": [ - "node_modules/bootstrap/dist/css/bootstrap.min.css", - "node_modules/@angular/material/prebuilt-themes/indigo-pink.css", - "node_modules/ngx-toastr/toastr.css", - "src/style/styles.scss" - ], - "stylePreprocessorOptions": { - "includePaths": ["src/style", "src/assets"] - }, - "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "3mb", - "maximumError": "5mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "300kb", - "maximumError": "400kb" - } - ], - "fileReplacements": [ - { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "frontend:build:production" - }, - "development": { - "proxyConfig": "src/proxy.conf.json", - "buildTarget": "frontend:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "frontend:build" - } - }, - "cypress-run": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve" - }, - "configurations": { - "production": { - "devServerTarget": "frontend:serve:production" - } - } - }, - "cypress-open": { - "builder": "@cypress/schematic:cypress", - "options": { - "watch": true, - "headless": false - } - }, - "ct": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve", - "watch": true, - "headless": false, - "testingType": "component" - }, - "configurations": { - "development": { - "devServerTarget": "frontend:serve:development" - } - } - }, - "e2e": { - "builder": "@cypress/schematic:cypress", - "options": { - "devServerTarget": "frontend:serve", - "watch": true, - "headless": false - }, - "configurations": { - "production": { - "devServerTarget": "frontend:serve:production" - } - } + "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "3mb", + "maximumError": "5mb" }, - "lint": { - "builder": "@angular-eslint/builder:lint", - "options": { - "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] - } + { + "type": "anyComponentStyle", + "maximumWarning": "300kb", + "maximumError": "400kb" } + ], + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "frontend:build:production" + }, + "development": { + "proxyConfig": "src/proxy.conf.json", + "buildTarget": "frontend:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "frontend:build" + } + }, + "cypress-run": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve" + }, + "configurations": { + "production": { + "devServerTarget": "frontend:serve:production" + } + } + }, + "cypress-open": { + "builder": "@cypress/schematic:cypress", + "options": { + "watch": true, + "headless": false + } + }, + "ct": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve", + "watch": true, + "headless": false, + "testingType": "component" + }, + "configurations": { + "development": { + "devServerTarget": "frontend:serve:development" + } + } + }, + "e2e": { + "builder": "@cypress/schematic:cypress", + "options": { + "devServerTarget": "frontend:serve", + "watch": true, + "headless": false + }, + "configurations": { + "production": { + "devServerTarget": "frontend:serve:production" } + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] + } } - }, - "cli": { - "analytics": false, - "schematicCollections": ["angular-eslint", "@cypress/schematic", "@schematics/angular"] + } } + }, + "cli": { + "analytics": false, + "schematicCollections": ["angular-eslint", "@cypress/schematic", "@schematics/angular"] + } } diff --git a/frontend/package.json b/frontend/package.json index 2fafd00da1..a73db31273 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,91 +1,91 @@ { - "name": "frontend", - "version": "2.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "build:staging": "ng build --configuration staging", - "watch": "ng build --watch --configuration development", - "watch:prod": "ng build --watch", - "test": "jest --silent", - "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", - "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", - "cypress:open": "cypress open", - "cypress:run": "cypress run --browser chrome", - "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", - "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", - "e2e": "ng e2e", - "format": "npm run lint:format", - "check": "npm run lint", - "lint:format:specific": "eslint --fix ", - "lint:format": "eslint --fix .", - "lint": "eslint .", - "prettier:lint:format:specific": "prettier --write", - "prettier:lint:format": "prettier --write .", - "prettier:lint": "prettier --check ." - }, - "private": true, - "dependencies": { - "@angular/animations": "^18.2.8", - "@angular/cdk": "^18.2.9", - "@angular/common": "^18.2.8", - "@angular/compiler": "^18.2.8", - "@angular/core": "^18.2.8", - "@angular/forms": "^18.2.8", - "@angular/material": "^18.2.9", - "@angular/material-moment-adapter": "^18.2.9", - "@angular/platform-browser": "^18.2.8", - "@angular/platform-browser-dynamic": "^18.2.8", - "@angular/router": "^18.2.8", - "@ngx-translate/core": "^16.0.0", - "@ngx-translate/http-loader": "^16.0.0", - "@stylistic/eslint-plugin": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "angular-oauth2-oidc": "^17.0.2", - "bootstrap": "^5.3.3", - "eslint-plugin-i18n-json": "^4.0.0", - "moment": "^2.30.1", - "ngx-toastr": "^19.0.0", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^18.2.9", - "@angular/cli": "~18.2.9", - "@angular/compiler-cli": "^18.2.8", - "@cypress/schematic": "^2.5.2", - "@cypress/skip-test": "^2.6.1", - "@eslint/js": "^9.15.0", - "@html-eslint/eslint-plugin": "^0.27.0", - "@html-eslint/parser": "^0.27.0", - "@types/eslint__js": "^8.42.3", - "@types/jest": "^29.5.13", - "@types/uuid": "^10.0.0", - "angular-eslint": "19.0.2", - "browserslist": "^4.24.2", - "cypress": "^13.15.0", - "cypress-real-events": "^1.13.0", - "eslint": "^9.16.0", - "eslint-plugin-unused-imports": "^4.1.4", - "jest": "^29.7.0", - "jest-preset-angular": "^14.2.4", - "ngx-translate-testing": "^7.0.0", - "prettier": "^3.4.2", - "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-config-standard-scss": "^14.0.0", - "typescript": "^5.5.4", - "typescript-eslint": "8.18.0", - "uuid": "^11.0.0" - }, - "jest": { - "preset": "jest-preset-angular", - "setupFilesAfterEnv": [ - "/setup-jest.ts" - ] - }, - "engines": { - "npm": ">=10.0.0 <12.0.0", - "node": ">=22.0.0 <23.0.0" - } + "name": "frontend", + "version": "2.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "build:staging": "ng build --configuration staging", + "watch": "ng build --watch --configuration development", + "watch:prod": "ng build --watch", + "test": "jest --silent", + "prestart": "cp scripts/pre-commit ../.git/hooks/ && chmod +x ../.git/hooks/pre-commit && echo 'hook copied'", + "prebuild": "version=$(grep -oP '\\K.*(?=-SNAPSHOT)' ../pom.xml); echo \"export const version = 'v$version';\" > src/app/version.ts\n", + "cypress:open": "cypress open", + "cypress:run": "cypress run --browser chrome", + "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", + "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", + "e2e": "ng e2e", + "format": "npm run lint:format", + "check": "npm run lint", + "lint:format:specific": "eslint --fix ", + "lint:format": "eslint --fix .", + "lint": "eslint .", + "prettier:lint:format:specific": "prettier --write", + "prettier:lint:format": "prettier --write .", + "prettier:lint": "prettier --check ." + }, + "private": true, + "dependencies": { + "@angular/animations": "^18.2.8", + "@angular/cdk": "^18.2.9", + "@angular/common": "^18.2.8", + "@angular/compiler": "^18.2.8", + "@angular/core": "^18.2.8", + "@angular/forms": "^18.2.8", + "@angular/material": "^18.2.9", + "@angular/material-moment-adapter": "^18.2.9", + "@angular/platform-browser": "^18.2.8", + "@angular/platform-browser-dynamic": "^18.2.8", + "@angular/router": "^18.2.8", + "@ngx-translate/core": "^16.0.0", + "@ngx-translate/http-loader": "^16.0.0", + "@stylistic/eslint-plugin": "^2.11.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "angular-oauth2-oidc": "^17.0.2", + "bootstrap": "^5.3.3", + "eslint-plugin-i18n-json": "^4.0.0", + "moment": "^2.30.1", + "ngx-toastr": "^19.0.0", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^18.2.9", + "@angular/cli": "~18.2.9", + "@angular/compiler-cli": "^18.2.8", + "@cypress/schematic": "^2.5.2", + "@cypress/skip-test": "^2.6.1", + "@eslint/js": "^9.15.0", + "@html-eslint/eslint-plugin": "^0.27.0", + "@html-eslint/parser": "^0.27.0", + "@types/eslint__js": "^8.42.3", + "@types/jest": "^29.5.13", + "@types/uuid": "^10.0.0", + "angular-eslint": "19.0.2", + "browserslist": "^4.24.2", + "cypress": "^13.15.0", + "cypress-real-events": "^1.13.0", + "eslint": "^9.16.0", + "eslint-plugin-unused-imports": "^4.1.4", + "jest": "^29.7.0", + "jest-preset-angular": "^14.2.4", + "ngx-translate-testing": "^7.0.0", + "prettier": "^3.4.2", + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-standard-scss": "^14.0.0", + "typescript": "^5.5.4", + "typescript-eslint": "8.18.0", + "uuid": "^11.0.0" + }, + "jest": { + "preset": "jest-preset-angular", + "setupFilesAfterEnv": [ + "/setup-jest.ts" + ] + }, + "engines": { + "npm": ">=10.0.0 <12.0.0", + "node": ">=22.0.0 <23.0.0" + } } From 1434bba9958223d4259bec8231c073dc81b24d60 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 10:57:56 +0100 Subject: [PATCH 54/78] update precommit hook to use prettier --- frontend/package.json | 4 ++-- frontend/scripts/pre-commit | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index a73db31273..48283757f1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,8 +16,8 @@ "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", "e2e": "ng e2e", - "format": "npm run lint:format", - "check": "npm run lint", + "format": "npm run lint:format && npm run prettier:lint:format", + "check": "npm run lint && npm run prettier:lint", "lint:format:specific": "eslint --fix ", "lint:format": "eslint --fix .", "lint": "eslint .", diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 6a1662a35e..486c460169 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -15,10 +15,16 @@ has_changed() { } - frontend_files=$(get_changed_files "$FRONTEND_PATH") backend_files=$(get_changed_files "$BACKEND_PATH") +echo "*****Running prettier******" +cd "$FRONTEND_PATH" || exit +has_changed "$frontend_files" && npm run prettier:lint:format:specific "$frontend_files" || echo "No files found to format" +echo "*****Finish running eslint******" + +echo "---------------------------------------------------------" + echo "*****Running eslint******" cd "$FRONTEND_PATH" || exit has_changed "$frontend_files" && npm run lint:format:specific "$frontend_files" || echo "No files found to format" @@ -27,9 +33,9 @@ echo "*****Finish running eslint******" echo "---------------------------------------------------------" echo "*****Running maven formatter******" -cd "$GIT_BASE_PATH" || exit +cd "$BACKEND_PATH" || exit # shellcheck disable=SC2091 -has_changed "$backend_files" && mvn -f backend/pom.xml spotless:apply -DspotlessFiles="$backend_files" || echo "No files found to format" +has_changed "$backend_files" && mvn -f pom.xml spotless:apply -DspotlessFiles="$backend_files" || echo "No files found to format" echo "*****Finish running maven formatter******" echo "---------------------------------------------------------" From f99a5ed4fcf62ac901cc4f62807c2becd797118f Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 11:05:26 +0100 Subject: [PATCH 55/78] replace new lines with space to read changed files --- frontend/scripts/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 486c460169..5fe2fa33ac 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -6,7 +6,7 @@ FRONTEND_PATH="$GIT_BASE_PATH"/frontend get_changed_files() { GIT_BASE_PATH=$(git rev-parse --show-toplevel) path=$1 - git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" + git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | tr '\n' ' ' } has_changed() { From ebfa8856bc6db75e2ecf07c8196eedc9ba5591f7 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 12:49:45 +0100 Subject: [PATCH 56/78] exclude files without extension from formatting --- frontend/scripts/pre-commit | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 5fe2fa33ac..2c5c55e9cf 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -2,11 +2,12 @@ GIT_BASE_PATH=$(git rev-parse --show-toplevel) BACKEND_PATH="$GIT_BASE_PATH"/backend FRONTEND_PATH="$GIT_BASE_PATH"/frontend +FORMATTED_FILE_EXTENSIONS="java|ts|html|xml|json|yml|yaml|mjs" get_changed_files() { GIT_BASE_PATH=$(git rev-parse --show-toplevel) path=$1 - git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | tr '\n' ' ' + git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | tr '\n' ' ' | xargs | grep "\.($FORMATTED_FILE_EXTENSIONS)$" } has_changed() { From 26a6633c334b45e3ba0788b8f249b6d93c7e6081 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 13:18:45 +0100 Subject: [PATCH 57/78] fix pre-commit hook --- frontend/eslint.config.mjs | 6 ------ frontend/package.json | 4 ++-- frontend/scripts/pre-commit | 9 +++++---- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 37ca0a0b51..1241cf9093 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -5,7 +5,6 @@ import stylistic from '@stylistic/eslint-plugin' import html from '@html-eslint/eslint-plugin' import angular from 'angular-eslint' import angularTemplateParser from '@angular-eslint/template-parser' -import scssConfig from 'stylelint-config-standard-scss' export default tsEslint.config( { @@ -78,11 +77,6 @@ export default tsEslint.config( '@html-eslint/indent': ['error', 2], }, }, - { - // files: ["**/*.scss"], - ...Object.fromEntries(Object.entries(scssConfig).filter(([k]) => k === '0')), - }, - { plugins: { 'unused-imports': unusedImports, diff --git a/frontend/package.json b/frontend/package.json index 48283757f1..aafbc03bb2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,10 +18,10 @@ "e2e": "ng e2e", "format": "npm run lint:format && npm run prettier:lint:format", "check": "npm run lint && npm run prettier:lint", - "lint:format:specific": "eslint --fix ", + "lint:format:specific": "eslint --fix --no-error-on-unmatched-pattern", "lint:format": "eslint --fix .", "lint": "eslint .", - "prettier:lint:format:specific": "prettier --write", + "prettier:lint:format:specific": "prettier --no-error-on-unmatched-pattern --write ", "prettier:lint:format": "prettier --write .", "prettier:lint": "prettier --check ." }, diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 2c5c55e9cf..4fc0a786c3 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -2,12 +2,14 @@ GIT_BASE_PATH=$(git rev-parse --show-toplevel) BACKEND_PATH="$GIT_BASE_PATH"/backend FRONTEND_PATH="$GIT_BASE_PATH"/frontend -FORMATTED_FILE_EXTENSIONS="java|ts|html|xml|json|yml|yaml|mjs" +FORMATTED_FILE_EXTENSIONS="java|ts|html|css|scss|xml|json|yml|yaml|mjs" get_changed_files() { - GIT_BASE_PATH=$(git rev-parse --show-toplevel) path=$1 - git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | tr '\n' ' ' | xargs | grep "\.($FORMATTED_FILE_EXTENSIONS)$" + GIT_BASE_PATH=$(git rev-parse --show-toplevel) + + + git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | grep -E "\.($FORMATTED_FILE_EXTENSIONS)$" | tr '\n' ' ' | xargs } has_changed() { @@ -18,7 +20,6 @@ has_changed() { frontend_files=$(get_changed_files "$FRONTEND_PATH") backend_files=$(get_changed_files "$BACKEND_PATH") - echo "*****Running prettier******" cd "$FRONTEND_PATH" || exit has_changed "$frontend_files" && npm run prettier:lint:format:specific "$frontend_files" || echo "No files found to format" From c2e9a95c606fa40b977f3e2338bbb66e4942bea9 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 12 Dec 2024 13:22:13 +0100 Subject: [PATCH 58/78] update name of package scripts and update workflow --- .github/workflows/format-action.yml | 2 +- frontend/package.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/format-action.yml b/.github/workflows/format-action.yml index e57db39e56..09bfaddb62 100644 --- a/.github/workflows/format-action.yml +++ b/.github/workflows/format-action.yml @@ -21,7 +21,7 @@ jobs: run: npm ci - name: Format frontend - run: npm run check + run: npm run check-linting:all backend: runs-on: ubuntu-latest diff --git a/frontend/package.json b/frontend/package.json index aafbc03bb2..48d4afbec3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,9 +16,9 @@ "cypress:open-test": "concurrently \"npm start\" \"cypress open\"", "cypress:run-test": "npm run build && concurrently \"npm run serve:dist\" \"cypress run\"", "e2e": "ng e2e", - "format": "npm run lint:format && npm run prettier:lint:format", - "check": "npm run lint && npm run prettier:lint", - "lint:format:specific": "eslint --fix --no-error-on-unmatched-pattern", + "format:all": "npm run lint:format && npm run prettier:lint:format", + "check-linting:all": "npm run lint && npm run prettier:lint", + "lint:format:specific": "eslint --fix --no-error-on-unmatched-pattern --no-warn-ignored", "lint:format": "eslint --fix .", "lint": "eslint .", "prettier:lint:format:specific": "prettier --no-error-on-unmatched-pattern --write ", From a6e33dc63cbec9c0c3f2702f952eb74ff1e7d7be Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 09:39:53 +0100 Subject: [PATCH 59/78] readd ignored files to prettierrc --- frontend/.prettierignore | 4 ++++ frontend/README.md | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/.prettierignore b/frontend/.prettierignore index 5f3d5e8993..50923ca6d2 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,2 +1,6 @@ +src/assets/ +dist/ +.angular/ +# The following files alredy getting formatting by eslint **/*.html **/*.ts diff --git a/frontend/README.md b/frontend/README.md index d6bf4073eb..79ee611146 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -30,9 +30,13 @@ Build: ## Formatting -We use the **EsLint** code formatter for the frontend code: + +We use **EsLint** and a variety of plugins to format html and ts files: https://eslint.org/ +We use **prettier** to format scss json and yaml files: +https://prettier.io/ + ## Test Coverage For generating the coverage of our frontend specs (jest), you can use following command: From f406925518c28b61cb017ebc4481b70d7afbd648 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 10:50:34 +0100 Subject: [PATCH 60/78] clean up --- frontend/.prettierrc | 2 +- frontend/package-lock.json | 8 ++++---- frontend/package.json | 4 ++-- frontend/scripts/pre-commit | 16 +++++++--------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/frontend/.prettierrc b/frontend/.prettierrc index b64bb3eae5..a7c979d034 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -5,7 +5,7 @@ "singleQuote": true, "overrides": [ { - "files": "**/*.json", + "files": "**/*.{json,scss}", "options": { "tabWidth": 2 } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 598dea2e7c..9f08b6476e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -52,7 +52,7 @@ "jest": "^29.7.0", "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", - "prettier": "^3.3.3", + "prettier": "^3.4.2", "stylelint-config-recommended-scss": "^14.1.0", "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", @@ -17713,9 +17713,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", "bin": { diff --git a/frontend/package.json b/frontend/package.json index 48d4afbec3..8ea1b91570 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,10 +18,10 @@ "e2e": "ng e2e", "format:all": "npm run lint:format && npm run prettier:lint:format", "check-linting:all": "npm run lint && npm run prettier:lint", - "lint:format:specific": "eslint --fix --no-error-on-unmatched-pattern --no-warn-ignored", + "lint:format:specific": "eslint --fix --no-warn-ignored", "lint:format": "eslint --fix .", "lint": "eslint .", - "prettier:lint:format:specific": "prettier --no-error-on-unmatched-pattern --write ", + "prettier:lint:format:specific": "prettier --write ", "prettier:lint:format": "prettier --write .", "prettier:lint": "prettier --check ." }, diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 4fc0a786c3..1741589f0d 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -7,8 +7,7 @@ FORMATTED_FILE_EXTENSIONS="java|ts|html|css|scss|xml|json|yml|yaml|mjs" get_changed_files() { path=$1 GIT_BASE_PATH=$(git rev-parse --show-toplevel) - - + # shellcheck disable=SC1087 git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | grep -E "\.($FORMATTED_FILE_EXTENSIONS)$" | tr '\n' ' ' | xargs } @@ -22,21 +21,20 @@ frontend_files=$(get_changed_files "$FRONTEND_PATH") backend_files=$(get_changed_files "$BACKEND_PATH") echo "*****Running prettier******" cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run prettier:lint:format:specific "$frontend_files" || echo "No files found to format" -echo "*****Finish running eslint******" +has_changed "$frontend_files" && npm run prettier:lint:format:specific $frontend_files || echo "No files found to format" +echo "*****Finish running prettier******" echo "---------------------------------------------------------" echo "*****Running eslint******" cd "$FRONTEND_PATH" || exit -has_changed "$frontend_files" && npm run lint:format:specific "$frontend_files" || echo "No files found to format" +has_changed "$frontend_files" && npm run lint:format:specific $frontend_files || echo "No files found to format" echo "*****Finish running eslint******" echo "---------------------------------------------------------" echo "*****Running maven formatter******" cd "$BACKEND_PATH" || exit -# shellcheck disable=SC2091 has_changed "$backend_files" && mvn -f pom.xml spotless:apply -DspotlessFiles="$backend_files" || echo "No files found to format" echo "*****Finish running maven formatter******" @@ -44,9 +42,9 @@ echo "---------------------------------------------------------" echo "*****Adding changes to git******" cd "$GIT_BASE_PATH" || exit - -has_changed "$frontend_files" && git add "$frontend_files" -v || echo "No frontend files changed, nothing to add" -has_changed "$backend_files" && git add "$backend_files" -v || echo "No backend files files changed, nothing to add" +echo "$frontend_files" +has_changed "$frontend_files" && git add $frontend_files -v || echo "No frontend files changed, nothing to add" +has_changed "$backend_files" && git add $backend_files -v || echo "No backend files files changed, nothing to add" echo "*****Formatted files added again******" status=$? From 178b6daacf4faa7892a032925e6348e7f3efd58a Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 11:12:33 +0100 Subject: [PATCH 61/78] clean up --- .../main/resources/formatters/Default-2.xml | 380 ------------------ .../src/main/resources/formatters/default.xml | 380 ------------------ frontend/setup-jest.ts | 2 +- .../action-plan/action-plan.component.scss | 8 +- 4 files changed, 3 insertions(+), 767 deletions(-) delete mode 100644 backend/src/main/resources/formatters/Default-2.xml delete mode 100644 backend/src/main/resources/formatters/default.xml diff --git a/backend/src/main/resources/formatters/Default-2.xml b/backend/src/main/resources/formatters/Default-2.xml deleted file mode 100644 index a5ae218a63..0000000000 --- a/backend/src/main/resources/formatters/Default-2.xml +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/backend/src/main/resources/formatters/default.xml b/backend/src/main/resources/formatters/default.xml deleted file mode 100644 index 8eb1587675..0000000000 --- a/backend/src/main/resources/formatters/default.xml +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/frontend/setup-jest.ts b/frontend/setup-jest.ts index 90bc5062ea..a702c63396 100644 --- a/frontend/setup-jest.ts +++ b/frontend/setup-jest.ts @@ -1 +1 @@ -import 'jest-preset-angular/setup-jest' +import "jest-preset-angular/setup-jest"; diff --git a/frontend/src/app/components/action-plan/action-plan.component.scss b/frontend/src/app/components/action-plan/action-plan.component.scss index 6f5232bd9a..ce0966283e 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.scss +++ b/frontend/src/app/components/action-plan/action-plan.component.scss @@ -7,18 +7,14 @@ height: 32px; } -.cdk-drag-preview - - -{ +.cdk-drag-preview { box-sizing: border-box; border-radius: 4px; box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12); - - } +} .cdk-drag-placeholder { opacity: 0; From a4017d08973c34862f9b6d37d7ac4838086b9f43 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 11:13:04 +0100 Subject: [PATCH 62/78] remove logs from pre-commit --- frontend/scripts/pre-commit | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index 1741589f0d..d802467f63 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -42,7 +42,6 @@ echo "---------------------------------------------------------" echo "*****Adding changes to git******" cd "$GIT_BASE_PATH" || exit -echo "$frontend_files" has_changed "$frontend_files" && git add $frontend_files -v || echo "No frontend files changed, nothing to add" has_changed "$backend_files" && git add $backend_files -v || echo "No backend files files changed, nothing to add" echo "*****Formatted files added again******" From 661416754bdfb162436b1b3831df69c725af160b Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 11:15:30 +0100 Subject: [PATCH 63/78] remove files from pr --- frontend/cypress.config.ts | 24 ++++++++++++------------ frontend/setup-jest.ts | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts index 15426169ed..b188ef99ec 100644 --- a/frontend/cypress.config.ts +++ b/frontend/cypress.config.ts @@ -1,14 +1,14 @@ -import { defineConfig } from 'cypress' +import { defineConfig } from 'cypress'; export default defineConfig({ - e2e: { - baseUrl: 'http://pitc.okr.localhost:4200', - experimentalMemoryManagement: true, - testIsolation: true, - viewportWidth: 1920, - viewportHeight: 1080, - }, - env: { - login_url: 'http://localhost:8544', - }, -}) + e2e: { + baseUrl: 'http://pitc.okr.localhost:4200', + experimentalMemoryManagement: true, + testIsolation: true, + viewportWidth: 1920, + viewportHeight: 1080, + }, + env: { + login_url: 'http://localhost:8544', + }, +}); diff --git a/frontend/setup-jest.ts b/frontend/setup-jest.ts index a702c63396..1100b3e8a6 100644 --- a/frontend/setup-jest.ts +++ b/frontend/setup-jest.ts @@ -1 +1 @@ -import "jest-preset-angular/setup-jest"; +import 'jest-preset-angular/setup-jest'; From edaae054947d5d7add0860cc346367f0644ada35 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 12:14:42 +0100 Subject: [PATCH 64/78] update frontend config --- frontend/eslint.config.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 1241cf9093..854cf42b33 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -34,8 +34,12 @@ export default tsEslint.config( '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }], '@stylistic/indent': ['error', 2], '@stylistic/quotes': ['error', 'double'], + '@stylistic/quote-props': ['error', 'as-needed'], + '@stylistic/object-property-newline': ['error'], '@stylistic/multiline-ternary': ['off'], '@stylistic/object-curly-spacing': ['error', 'always'], + '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], + '@stylistic/semi-style': ['error'], '@angular-eslint/directive-selector': [ 'error', { From e9285a3deba29fa6bdc932215f667ae452522d30 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 12:48:10 +0100 Subject: [PATCH 65/78] allow empty constructors --- frontend/eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 854cf42b33..8cec73562e 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -27,6 +27,7 @@ export default tsEslint.config( '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-namespace': 'off', 'prefer-rest-params': 'off', + '@typescript-eslint-no-empty-function': ['error', { allow: ['constructors'] }], //stylistic rules '@stylistic/function-call-argument-newline': ['error', 'never'], '@stylistic/padded-blocks': ['error', 'never'], From a897a702bc644bb744e2439ed5c53330569fa16f Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 13:32:37 +0100 Subject: [PATCH 66/78] update config --- frontend/eslint.config.mjs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 8cec73562e..b582b228e1 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -19,6 +19,7 @@ export default tsEslint.config( rules: { ...stylistic.configs['all-flat'].rules, 'unused-imports/no-unused-imports': 'error', + // ToDo: Disable rules so eslint passes, fix in followup ticket '@typescript-eslint/no-unused-vars': 'off', '@typescript-eslint/no-unused-expressions': 'off', @@ -27,25 +28,40 @@ export default tsEslint.config( '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-namespace': 'off', 'prefer-rest-params': 'off', - '@typescript-eslint-no-empty-function': ['error', { allow: ['constructors'] }], - //stylistic rules - '@stylistic/function-call-argument-newline': ['error', 'never'], + '@typescript-eslint/no-empty-function': ['off'], + '@stylistic/lines-around-comment': ['off'], + '@angular-eslint/no-empty-lifecycle-method': 'off', + '@angular-eslint/component-class-suffix': 'off', + '@angular-eslint/template/eqeqeq': 'off', + '@angular-eslint/template/interactive-supports-focus': 'off', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@stylistic/no-extra-parens': 'off', + '@typescript-eslint/no-confusing-non-null-assertion': 'off', + //Delete these rules after fixing all the issues and enabling the actual rules + '@stylistic/quotes': 'off', + '@stylistic/function-call-argument-newline': 'off', + + //Actual formatting rules + // '@stylistic/function-call-argument-newline': ['error', 'never'], + // '@stylistic/quotes': ['error', 'double'], '@stylistic/padded-blocks': ['error', 'never'], '@stylistic/dot-location': ['error', 'property'], '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }], '@stylistic/indent': ['error', 2], - '@stylistic/quotes': ['error', 'double'], '@stylistic/quote-props': ['error', 'as-needed'], '@stylistic/object-property-newline': ['error'], '@stylistic/multiline-ternary': ['off'], '@stylistic/object-curly-spacing': ['error', 'always'], '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], '@stylistic/semi-style': ['error'], + '@stylistic/function-paren-newline': ['error', { minItems: 4 }], '@angular-eslint/directive-selector': [ 'error', { type: 'attribute', - prefix: 'app', + // reenable this after fixing all the directives + // prefix: 'app', style: 'camelCase', }, ], @@ -64,6 +80,7 @@ export default tsEslint.config( rules: { '@typescript-eslint/no-explicit-any': 'off', 'prefer-rest-params': 'off', + '@typescript-eslint/no-empty-function': 'off', }, }, { @@ -78,6 +95,10 @@ export default tsEslint.config( // ToDo: Disable rules so eslint passes, fix in followup ticket '@html-eslint/require-img-alt': 'off', '@html-eslint/element-newline': 'off', + '@angular-eslint/template/eqeqeq': 'off', + '@angular-eslint/template/interactive-supports-focus': 'off', + '@angular-eslint/directive-selector': 'off', + '@angular-eslint/template/click-events-have-key-events': 'off', //stylistic rules '@html-eslint/indent': ['error', 2], }, From 94e04f0d4b2e9b4c5c777bf791d38f61a544d4ad Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 13:36:40 +0100 Subject: [PATCH 67/78] update prettirrc --- frontend/.prettierrc | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/frontend/.prettierrc b/frontend/.prettierrc index a7c979d034..cc9131084c 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,14 +1,6 @@ { "trailingComma": "es5", - "tabWidth": 4, + "tabWidth": 2, "semi": false, "singleQuote": true, - "overrides": [ - { - "files": "**/*.{json,scss}", - "options": { - "tabWidth": 2 - } - } - ] } From 3ed2b96c32914b7192745bca601b9eb66bc1a0ba Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 15:48:16 +0100 Subject: [PATCH 68/78] update config --- frontend/eslint.config.mjs | 194 ++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index b582b228e1..cb726005db 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -5,109 +5,109 @@ import stylistic from '@stylistic/eslint-plugin' import html from '@html-eslint/eslint-plugin' import angular from 'angular-eslint' import angularTemplateParser from '@angular-eslint/template-parser' +import htmlParser from '@html-eslint/parser' export default tsEslint.config( - { - files: ['**/*.ts'], - extends: [ - eslint.configs.recommended, - ...tsEslint.configs.recommended, - ...tsEslint.configs.stylistic, - ...angular.configs.tsRecommended, - ], - processor: angular.processInlineTemplates, - rules: { - ...stylistic.configs['all-flat'].rules, - 'unused-imports/no-unused-imports': 'error', + { + files: ['**/*.ts'], + extends: [ + eslint.configs.recommended, + ...tsEslint.configs.recommended, + ...tsEslint.configs.stylistic, + ...angular.configs.tsRecommended, + ], + processor: angular.processInlineTemplates, + rules: { + ...stylistic.configs['all-flat'].rules, + 'unused-imports/no-unused-imports': 'error', - // ToDo: Disable rules so eslint passes, fix in followup ticket - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-unused-expressions': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - 'no-undef': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-namespace': 'off', - 'prefer-rest-params': 'off', - '@typescript-eslint/no-empty-function': ['off'], - '@stylistic/lines-around-comment': ['off'], - '@angular-eslint/no-empty-lifecycle-method': 'off', - '@angular-eslint/component-class-suffix': 'off', - '@angular-eslint/template/eqeqeq': 'off', - '@angular-eslint/template/interactive-supports-focus': 'off', - '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@stylistic/no-extra-parens': 'off', - '@typescript-eslint/no-confusing-non-null-assertion': 'off', - //Delete these rules after fixing all the issues and enabling the actual rules - '@stylistic/quotes': 'off', - '@stylistic/function-call-argument-newline': 'off', + // ToDo: Disable rules so eslint passes, fix in followup ticket + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + 'no-undef': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-namespace': 'off', + 'prefer-rest-params': 'off', + '@typescript-eslint/no-empty-function': ['off'], + '@stylistic/lines-around-comment': ['off'], + '@angular-eslint/no-empty-lifecycle-method': 'off', + '@angular-eslint/component-class-suffix': 'off', + '@angular-eslint/template/eqeqeq': 'off', + '@angular-eslint/template/interactive-supports-focus': 'off', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@stylistic/no-extra-parens': 'off', + '@typescript-eslint/no-confusing-non-null-assertion': 'off', + //Delete these rules after fixing all the issues and enabling the actual rules + '@stylistic/quotes': 'off', + '@stylistic/function-call-argument-newline': 'off', - //Actual formatting rules - // '@stylistic/function-call-argument-newline': ['error', 'never'], - // '@stylistic/quotes': ['error', 'double'], - '@stylistic/padded-blocks': ['error', 'never'], - '@stylistic/dot-location': ['error', 'property'], - '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }], - '@stylistic/indent': ['error', 2], - '@stylistic/quote-props': ['error', 'as-needed'], - '@stylistic/object-property-newline': ['error'], - '@stylistic/multiline-ternary': ['off'], - '@stylistic/object-curly-spacing': ['error', 'always'], - '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], - '@stylistic/semi-style': ['error'], - '@stylistic/function-paren-newline': ['error', { minItems: 4 }], - '@angular-eslint/directive-selector': [ - 'error', - { - type: 'attribute', - // reenable this after fixing all the directives - // prefix: 'app', - style: 'camelCase', - }, - ], - '@angular-eslint/component-selector': [ - 'error', - { - type: 'element', - prefix: 'app', - style: 'kebab-case', - }, - ], + //Actual formatting rules + // '@stylistic/function-call-argument-newline': ['error', 'never'], + // '@stylistic/quotes': ['error', 'double'], + '@stylistic/padded-blocks': ['error', 'never'], + '@stylistic/dot-location': ['error', 'property'], + '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 1 }], + '@stylistic/indent': ['error', 2], + '@stylistic/quote-props': ['error', 'as-needed'], + '@stylistic/object-property-newline': ['error'], + '@stylistic/multiline-ternary': ['off'], + '@stylistic/object-curly-spacing': ['error', 'always'], + '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], + '@stylistic/semi-style': ['error'], + '@stylistic/function-paren-newline': ['error', { minItems: 4 }], + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + // reenable this after fixing all the directives + // prefix: 'app', + style: 'camelCase', }, - }, - { - files: ['**/*.spec.ts'], - rules: { - '@typescript-eslint/no-explicit-any': 'off', - 'prefer-rest-params': 'off', - '@typescript-eslint/no-empty-function': 'off', + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'app', + style: 'kebab-case', }, + ], }, - { - files: ['**/*.html'], - extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], - processor: angular.processInlineTemplates, - languageOptions: { - parser: angularTemplateParser, - }, - rules: { - ...html.configs.recommended.rules, - // ToDo: Disable rules so eslint passes, fix in followup ticket - '@html-eslint/require-img-alt': 'off', - '@html-eslint/element-newline': 'off', - '@angular-eslint/template/eqeqeq': 'off', - '@angular-eslint/template/interactive-supports-focus': 'off', - '@angular-eslint/directive-selector': 'off', - '@angular-eslint/template/click-events-have-key-events': 'off', - //stylistic rules - '@html-eslint/indent': ['error', 2], - }, + }, + { + files: ['**/*.spec.ts'], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + 'prefer-rest-params': 'off', + '@typescript-eslint/no-empty-function': 'off', }, - { - plugins: { - 'unused-imports': unusedImports, - '@stylistic': stylistic, - '@html-eslint': html, - }, - } + }, + + { + files: ['**/*.html'], + // recommended configuration included in the plugin + ...html.configs['flat/recommended'], + //extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], + //processor: angular.processInlineTemplates, + //languageOptions: { + //parser: angularTemplateParser, + //}, + languageOptions: { + parser: htmlParser, + }, + rules: { + ...html.configs['flat/recommended'].rules, + // Must be defined. If not, all recommended rules will be lost + '@html-eslint/indent': ['error', 2], + }, + }, + { + plugins: { + 'unused-imports': unusedImports, + '@stylistic': stylistic, + '@html-eslint': html, + }, + } ) From 006382677a9f378ca73a40512763af2573c549ff Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 13 Dec 2024 15:51:04 +0100 Subject: [PATCH 69/78] use old html formatter --- frontend/eslint.config.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index cb726005db..e20fa5075b 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -101,6 +101,8 @@ export default tsEslint.config( ...html.configs['flat/recommended'].rules, // Must be defined. If not, all recommended rules will be lost '@html-eslint/indent': ['error', 2], + '@html-eslint/require-img-alt': 'off', + '@html-eslint/element-newline': 'off', }, }, { From 4cbf3761736a5f8e966374ba8b610a001c66d89c Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 16 Dec 2024 08:08:16 +0100 Subject: [PATCH 70/78] rmeove xargs from precommit hook --- frontend/scripts/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/scripts/pre-commit b/frontend/scripts/pre-commit index d802467f63..4e6bf298d3 100755 --- a/frontend/scripts/pre-commit +++ b/frontend/scripts/pre-commit @@ -8,7 +8,7 @@ get_changed_files() { path=$1 GIT_BASE_PATH=$(git rev-parse --show-toplevel) # shellcheck disable=SC1087 - git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | grep -E "\.($FORMATTED_FILE_EXTENSIONS)$" | tr '\n' ' ' | xargs + git diff --cached --name-only --diff-filter=d --line-prefix="$GIT_BASE_PATH"/ "$path" | grep -E "\.($FORMATTED_FILE_EXTENSIONS)$" | tr '\n' ' ' } has_changed() { From 5cf16c1f60354d0075f9947f1798aa54f90080b7 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Mon, 16 Dec 2024 12:51:38 +0100 Subject: [PATCH 71/78] update config for html files --- frontend/eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index e20fa5075b..c8fad5dbca 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -103,6 +103,7 @@ export default tsEslint.config( '@html-eslint/indent': ['error', 2], '@html-eslint/require-img-alt': 'off', '@html-eslint/element-newline': 'off', + '@html-eslint/require-closing-tags': ['error', { selfClosing: 'always' }], }, }, { From 07de984080f345908932c320e342cadd901cdfb5 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Wed, 18 Dec 2024 13:28:30 +0100 Subject: [PATCH 72/78] updat package lock --- frontend/package-lock.json | 5571 ++++++++++++------------------------ 1 file changed, 1798 insertions(+), 3773 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9f08b6476e..27f1fcdc2b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -313,13 +313,13 @@ } }, "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/architect": { - "version": "0.1900.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.4.tgz", - "integrity": "sha512-9XwZ21BPYS2vGOOwVB40fsMyuwJT0H1lWaAMo8Umwi6XbKBVfaWbEhjtR9dlarrySKtFuTz9hmTZkIXHLjXPdA==", + "version": "0.1900.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.5.tgz", + "integrity": "sha512-JxgoIxwGw3QNj6e70d04g5yJ8ZK0g/my22UK0TlRJRbYcfFQr8pL7u3wq77iNlgeHMDwBskZEf4TEZOVSbm7mw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.4", + "@angular-devkit/core": "19.0.5", "rxjs": "7.8.1" }, "engines": { @@ -329,9 +329,9 @@ } }, "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/core": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", - "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", + "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", "dev": true, "license": "MIT", "dependencies": { @@ -356,40 +356,6 @@ } } }, - "node_modules/@angular-eslint/builder/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-eslint/builder/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/bundled-angular-compiler": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", @@ -449,9 +415,9 @@ } }, "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/core": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", - "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", + "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", "dev": true, "license": "MIT", "dependencies": { @@ -477,13 +443,13 @@ } }, "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/schematics": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.4.tgz", - "integrity": "sha512-2r6Qs4N5NSPho+qzegCYS8kIgylXyH4DHaS7HJ5+4XvM1I8V8AII8payLWkUK0i29XufVoD5XfPUFnjxZrBfYQ==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.5.tgz", + "integrity": "sha512-dhLVBVb0ECfcIP59azoD/5lJMSMU//bo1LEbuE0VrFA9orVxQhgilNuZeVXBr5sOll1PFjxs/fqyX8sAH9xQYw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.4", + "@angular-devkit/core": "19.0.5", "jsonc-parser": "3.3.1", "magic-string": "0.30.12", "ora": "5.4.1", @@ -495,24 +461,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-eslint/schematics/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/schematics/node_modules/ignore": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", @@ -533,22 +481,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/@angular-eslint/schematics/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/template-parser": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", @@ -564,23 +496,6 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/template-parser/node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@angular-eslint/utils": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", @@ -597,9 +512,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.12.tgz", - "integrity": "sha512-XcWH/VFQ1Rddhdqi/iU8lW3Qg96yVx1NPfrO5lhcSSvVUzYWTZ5r+jh3GqYqUgPWyEp1Kpw3FLsOgVcGcBWQkQ==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.13.tgz", + "integrity": "sha512-rG5J5Ek5Hg+Tz2NjkNOaG6PupiNK/lPfophXpsR1t/nWujqnMWX2krahD/i6kgD+jNWNKCJCYSOVvCx/BHOtKA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -608,7 +523,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.12" + "@angular/core": "18.2.13" } }, "node_modules/@angular/build": { @@ -732,9 +647,9 @@ } }, "node_modules/@angular/common": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.12.tgz", - "integrity": "sha512-gI5o8Bccsi8ow8Wk2vG4Tw/Rw9LoHEA9j8+qHKNR/55SCBsz68Syg310dSyxy+sApJO2WiqIadr5VP36dlSUFw==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.13.tgz", + "integrity": "sha512-4ZqrNp1PoZo7VNvW+sbSc2CB2axP1sCH2wXl8B0wdjsj8JY1hF1OhuugwhpAHtGxqewed2kCXayE+ZJqSTV4jw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -743,14 +658,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.12", + "@angular/core": "18.2.13", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.12.tgz", - "integrity": "sha512-D5d5dLrjQal5DbAXJJNSsCC3UxzjOI2wbc+Iv+LOpRM1gpNwuYfZMX5W7cj62Ce4G2++78CJSppdKBp8D4HErQ==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.13.tgz", + "integrity": "sha512-TzWcrkopyjFF+WeDr2cRe8CcHjU72KfYV3Sm2TkBkcXrkYX5sDjGWrBGrG3hRB4e4okqchrOCvm1MiTdy2vKMA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -759,7 +674,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.12" + "@angular/core": "18.2.13" }, "peerDependenciesMeta": { "@angular/core": { @@ -768,9 +683,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.12.tgz", - "integrity": "sha512-IWimTNq5Q+i2Wxev6HLqnN4iYbPvLz04W1BBycT1LfGUsHcjFYLuUqbeUzHbk2snmBAzXkixgVpo8SF6P4Y5Pg==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.13.tgz", + "integrity": "sha512-DBSh4AQwkiJDSiVvJATRmjxf6wyUs9pwQLgaFdSlfuTRO+sdb0J2z1r3BYm8t0IqdoyXzdZq2YCH43EmyvD71g==", "dev": true, "license": "MIT", "dependencies": { @@ -792,44 +707,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.12", + "@angular/compiler": "18.2.13", "typescript": ">=5.4 <5.6" } }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.12.tgz", - "integrity": "sha512-wCf/OObwS6bpM60rk6bpMpCRGp0DlMLB1WNAMtfcaPNyqimVV5Bm98mWRhkOuRyvU3fU7iHhM/10ePVaoyu9+A==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.13.tgz", + "integrity": "sha512-8mbWHMgO95OuFV1Ejy4oKmbe9NOJ3WazQf/f7wks8Bck7pcihd0IKhlPBNjFllbF5o+04EYSwFhEtvEgjMDClA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -843,9 +728,9 @@ } }, "node_modules/@angular/forms": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.12.tgz", - "integrity": "sha512-FsukBJEU6jfAmht7TrODTkct/o4iwCZvGozuThOp0tYUPD/E1rZZzuKjEyTnT5Azpfkf0Wqx1nmpz80cczELOQ==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.13.tgz", + "integrity": "sha512-A67D867fu3DSBhdLWWZl/F5pr7v2+dRM2u3U7ZJ0ewh4a+sv+0yqWdJW+a8xIoiHxS+btGEJL2qAKJiH+MCFfg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -854,9 +739,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.12", - "@angular/core": "18.2.12", - "@angular/platform-browser": "18.2.12", + "@angular/common": "18.2.13", + "@angular/core": "18.2.13", + "@angular/platform-browser": "18.2.13", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -893,9 +778,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.12.tgz", - "integrity": "sha512-DRSMznuxuecrs+v5BRyd60/R4vjkQtuYUEPfzdo+rqxM83Dmr3PGtnqPRgd5oAFUbATxf02hQXijRD27K7rZRg==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.13.tgz", + "integrity": "sha512-tu7ZzY6qD3ATdWFzcTcsAKe7M6cJeWbT/4/bF9unyGO3XBPcNYDKoiz10+7ap2PUd0fmPwvuvTvSNJiFEBnB8Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -904,9 +789,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.12", - "@angular/common": "18.2.12", - "@angular/core": "18.2.12" + "@angular/animations": "18.2.13", + "@angular/common": "18.2.13", + "@angular/core": "18.2.13" }, "peerDependenciesMeta": { "@angular/animations": { @@ -915,9 +800,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.12.tgz", - "integrity": "sha512-dv1QEjYpcFno6+oUeGEDRWpB5g2Ufb0XkUbLJQIgrOk1Qbyzb8tmpDpTjok8jcKdquigMRWolr6Y1EOicfRlLw==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.13.tgz", + "integrity": "sha512-kbQCf9+8EpuJC7buBxhSiwBtXvjAwAKh6MznD6zd2pyCYqfY6gfRCZQRtK59IfgVtKmEONWI9grEyNIRoTmqJg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -926,16 +811,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.12", - "@angular/compiler": "18.2.12", - "@angular/core": "18.2.12", - "@angular/platform-browser": "18.2.12" + "@angular/common": "18.2.13", + "@angular/compiler": "18.2.13", + "@angular/core": "18.2.13", + "@angular/platform-browser": "18.2.13" } }, "node_modules/@angular/router": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.12.tgz", - "integrity": "sha512-cz/1YWOZadAT35PPPYmpK3HSzKOE56nlUHue5bFkw73VSZr2iBn03ALLpd9YKzWgRmx3y7DqnlQtCkDu9JPGKQ==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.13.tgz", + "integrity": "sha512-VKmfgi/r/CkyBq9nChQ/ptmfu0JT/8ONnLVJ5H+SkFLRYJcIRyHLKjRihMCyVm6xM5yktOdCaW73NTQrFz7+bg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -944,19 +829,20 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.12", - "@angular/core": "18.2.12", - "@angular/platform-browser": "18.2.12", + "@angular/common": "18.2.13", + "@angular/core": "18.2.13", + "@angular/platform-browser": "18.2.13", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@babel/code-frame": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz", - "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -964,9 +850,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz", - "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", "dev": true, "license": "MIT", "engines": { @@ -1050,20 +936,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", - "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-compilation-targets": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", @@ -1137,14 +1009,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", - "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.1.1", + "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "engines": { @@ -1178,9 +1050,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", "dev": true, "license": "MIT", "dependencies": { @@ -1223,14 +1095,13 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz", - "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, @@ -1313,20 +1184,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", - "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", @@ -1399,42 +1256,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz", - "integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", - "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -1622,9 +1464,9 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.9.tgz", - "integrity": "sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", "dependencies": { @@ -1941,9 +1783,9 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.9.tgz", - "integrity": "sha512-UIf+72C7YJ+PJ685/PpATbCz00XqiFEzHX5iysRwfvNT0Ko+FaXSvRgLytFSp8xUItrG9pFM/KoBBZDrY/cYyg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2091,13 +1933,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", - "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { @@ -2240,15 +2081,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", - "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2870,17 +2710,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2889,13 +2729,14 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz", - "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -2905,9 +2746,9 @@ } }, "node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { @@ -2918,9 +2759,9 @@ } }, "node_modules/@babel/types": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", - "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "license": "MIT", "dependencies": { @@ -3019,10 +2860,34 @@ "@csstools/css-tokenizer": "^3.0.3" } }, + "node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peer": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, "node_modules/@cypress/request": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", - "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", + "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3039,7 +2904,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.13.0", + "qs": "6.13.1", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -3049,19 +2914,6 @@ "node": ">= 6" } }, - "node_modules/@cypress/request/node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@cypress/request/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -3618,6 +3470,28 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/core": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", @@ -3669,11 +3543,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", @@ -3687,32 +3565,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "license": "MIT" }, - "node_modules/@eslint/js": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", - "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } }, "node_modules/@eslint/object-schema": { "version": "2.1.5", @@ -3969,9 +3847,9 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz", - "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", "dev": true, "license": "MIT", "engines": { @@ -4224,116 +4102,137 @@ "node": ">=8" } }, - "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==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jest/console/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==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "p-locate": "^4.1.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/console/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==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/@jest/console/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/@jest/console/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==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "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/@jest/console/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==", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4386,64 +4285,17 @@ } } }, - "node_modules/@jest/core/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/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/core/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/@jest/core/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/@jest/core/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==", + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "engines": { "node": ">=8" @@ -4459,19 +4311,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/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/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -4593,118 +4432,42 @@ } } }, - "node_modules/@jest/reporters/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==", + "node_modules/@jest/reporters/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "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/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/reporters/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==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/reporters/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/@jest/reporters/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/@jest/reporters/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/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/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { @@ -4776,59 +4539,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/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/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/transform/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/@jest/transform/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/@jest/transform/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4836,16 +4546,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@jest/transform/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/@jest/transform/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4856,19 +4556,6 @@ "node": ">=8" } }, - "node_modules/@jest/transform/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/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -4887,86 +4574,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/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/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/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/@jest/types/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/@jest/types/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/@jest/types/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/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "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": { @@ -5045,9 +4656,9 @@ } }, "node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", - "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.1.tgz", + "integrity": "sha512-osjeBqMJ2lb/j/M8NCPjs1ylqWIcTRTycIhVB5pt6LgzgeRSb0YRZ7j9RfA8wIUrsr/medIuhVyonXRZWLyfdw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5504,16 +5115,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@npmcli/package-json/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/@npmcli/package-json/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -5535,22 +5136,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@npmcli/package-json/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/@npmcli/promise-spawn": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", @@ -6028,9 +5613,9 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.0.tgz", - "integrity": "sha512-IvD2WXbOoSp0zNpyYbjdSyEjZtut78RYfj2WIlbChE7HFuposTK5X1hc5+4AyqYcjLXYdD5oo/sJtqMGFNRb1w==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz", + "integrity": "sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==", "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^8.13.0", @@ -6080,32 +5665,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@tufjs/models/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/@tufjs/models/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/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -6215,10 +5774,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, "node_modules/@types/express": { @@ -6235,9 +5793,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", - "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", + "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", "dev": true, "license": "MIT", "dependencies": { @@ -6361,13 +5919,13 @@ } }, "node_modules/@types/node": { - "version": "22.7.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", - "integrity": "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.20.0" } }, "node_modules/@types/node-forge": { @@ -6381,9 +5939,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", - "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", "dev": true, "license": "MIT" }, @@ -6487,9 +6045,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "dev": true, "license": "MIT", "dependencies": { @@ -6525,16 +6083,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz", - "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz", + "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==", "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.18.0", - "@typescript-eslint/type-utils": "8.18.0", - "@typescript-eslint/utils": "8.18.0", - "@typescript-eslint/visitor-keys": "8.18.0", + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/type-utils": "8.18.1", + "@typescript-eslint/utils": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -6554,15 +6112,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz", - "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==", - "license": "MITClause", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz", + "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", + "license": "MIT", + "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.18.0", - "@typescript-eslint/types": "8.18.0", - "@typescript-eslint/typescript-estree": "8.18.0", - "@typescript-eslint/visitor-keys": "8.18.0", + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/typescript-estree": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "debug": "^4.3.4" }, "engines": { @@ -6578,13 +6137,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz", - "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", + "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.0", - "@typescript-eslint/visitor-keys": "8.18.0" + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6595,13 +6154,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz", - "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz", + "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.18.0", - "@typescript-eslint/utils": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.1", + "@typescript-eslint/utils": "8.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -6618,9 +6177,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz", - "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", + "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6631,13 +6190,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz", - "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", + "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.0", - "@typescript-eslint/visitor-keys": "8.18.0", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -6656,40 +6215,16 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/typescript-estree/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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz", - "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", + "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.0", - "@typescript-eslint/types": "8.18.0", - "@typescript-eslint/typescript-estree": "8.18.0" + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/typescript-estree": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6704,12 +6239,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz", - "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", + "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/types": "8.18.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -6734,73 +6269,73 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", "dependencies": { @@ -6808,9 +6343,9 @@ } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6818,79 +6353,79 @@ } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -7042,14 +6577,11 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } @@ -7068,6 +6600,16 @@ "node": ">=8" } }, + "node_modules/aggregate-error/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -7140,9 +6682,9 @@ } }, "node_modules/angular-eslint/node_modules/@angular-devkit/core": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", - "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", + "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", "dev": true, "license": "MIT", "dependencies": { @@ -7168,13 +6710,13 @@ } }, "node_modules/angular-eslint/node_modules/@angular-devkit/schematics": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.4.tgz", - "integrity": "sha512-2r6Qs4N5NSPho+qzegCYS8kIgylXyH4DHaS7HJ5+4XvM1I8V8AII8payLWkUK0i29XufVoD5XfPUFnjxZrBfYQ==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.5.tgz", + "integrity": "sha512-dhLVBVb0ECfcIP59azoD/5lJMSMU//bo1LEbuE0VrFA9orVxQhgilNuZeVXBr5sOll1PFjxs/fqyX8sAH9xQYw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.4", + "@angular-devkit/core": "19.0.5", "jsonc-parser": "3.3.1", "magic-string": "0.30.12", "ora": "5.4.1", @@ -7186,24 +6728,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/angular-eslint/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/angular-eslint/node_modules/magic-string": { "version": "0.30.12", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", @@ -7214,22 +6738,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/angular-eslint/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/angular-oauth2-oidc": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-17.0.2.tgz", @@ -7293,15 +6801,18 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { @@ -7353,14 +6864,10 @@ "license": "MIT" }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/aria-query": { "version": "5.3.2", @@ -7531,69 +7038,6 @@ "@babel/core": "^7.8.0" } }, - "node_modules/babel-jest/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/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-jest/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/babel-jest/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/babel-jest/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/babel-jest/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7604,19 +7048,6 @@ "node": ">=8" } }, - "node_modules/babel-jest/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/babel-loader": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", @@ -7696,14 +7127,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", + "@babel/helper-define-polyfill-provider": "^0.6.3", "semver": "^6.3.1" }, "peerDependencies": { @@ -7735,13 +7166,13 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "@babel/helper-define-polyfill-provider": "^0.6.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -7909,16 +7340,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -7936,10 +7357,26 @@ "dev": true, "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7974,13 +7411,12 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -8110,9 +7546,9 @@ } }, "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { @@ -8143,16 +7579,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/cacache/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/cacache/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -8181,22 +7607,6 @@ "dev": true, "license": "ISC" }, - "node_modules/cacache/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/cachedir": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", @@ -8207,18 +7617,29 @@ "node": ">=6" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -8247,9 +7668,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001688", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz", - "integrity": "sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "dev": true, "funding": [ { @@ -8275,17 +7696,19 @@ "license": "Apache-2.0" }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/char-regex": { @@ -8316,41 +7739,19 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.2.tgz", + "integrity": "sha512-/b57FK+bblSU+dfewfFe0rT1YjVDfOmeLQwCAuC+vwvgLkXboATqqmy+Ipux6JrF6L5joe5CBnFOw+gLWH6yKg==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" } }, "node_modules/chownr": { @@ -8374,9 +7775,9 @@ } }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", + "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", "dev": true, "funding": [ { @@ -8544,42 +7945,6 @@ "node": ">=12" } }, - "node_modules/cliui/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/cliui/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/cliui/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/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -8655,18 +8020,21 @@ "license": "MIT" }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/colord": { @@ -8738,18 +8106,18 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", + "negotiator": "~0.6.4", "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { @@ -8773,13 +8141,6 @@ "dev": true, "license": "MIT" }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -8882,13 +8243,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -8929,26 +8290,6 @@ } } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -8971,86 +8312,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/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/create-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/create-jest/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/create-jest/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/create-jest/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/create-jest/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/critters": { "version": "0.0.24", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz", "integrity": "sha512-Oyqew0FGM0wYUSNqR0L6AteO5MpMoUU0rhKRieXeiKs+PmRTxiJMyaunYB2KF6fQ3dzChXKCpbFOEJx3OQ1v/Q==", + "deprecated": "Ownership of Critters has moved to the Nuxt team, who will be maintaining the project going forward. If you'd like to keep using Critters, please switch to the actively-maintained fork at https://github.com/danielroe/beasties", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9063,86 +8329,10 @@ "postcss-media-query-parser": "^0.2.3" } }, - "node_modules/critters/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/critters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/critters/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/critters/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/critters/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/critters/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/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -9353,68 +8543,6 @@ "cypress": "^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x || ^13.x" } }, - "node_modules/cypress/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/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cypress/node_modules/chalk/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/cypress/node_modules/ci-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", - "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cypress/node_modules/cli-truncate": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", @@ -9432,36 +8560,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cypress/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/cypress/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/cypress/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/cypress/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", @@ -9622,9 +8720,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -9785,24 +8883,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -10004,6 +9084,21 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -10053,9 +9148,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.73", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz", - "integrity": "sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==", + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", "dev": true, "license": "ISC" }, @@ -10229,14 +9324,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -10265,6 +9357,19 @@ "dev": true, "license": "MIT" }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", @@ -10336,12 +9441,15 @@ "license": "MIT" }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escodegen": { @@ -10378,9 +9486,9 @@ } }, "node_modules/eslint": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", - "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -10388,7 +9496,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.9.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.16.0", + "@eslint/js": "9.17.0", "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -10397,7 +9505,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -10471,191 +9579,116 @@ "node": ">=4" } }, - "node_modules/eslint-plugin-i18n-json/node_modules/indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "node_modules/eslint-plugin-i18n-json/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { "node": ">=4" } }, - "node_modules/eslint-plugin-i18n-json/node_modules/jest-diff": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", - "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", - "license": "MIT", - "dependencies": { - "chalk": "^2.0.1", - "diff": "^3.2.0", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "license": "MIT" - }, - "node_modules/eslint-plugin-i18n-json/node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "node_modules/eslint-plugin-i18n-json/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "license": "MIT", "dependencies": { - "chalk": "^2.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, - "node_modules/eslint-plugin-i18n-json/node_modules/pretty-format": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", - "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "node_modules/eslint-plugin-i18n-json/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", "dependencies": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "color-name": "1.1.3" } }, - "node_modules/eslint-plugin-unused-imports": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", - "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^9.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } + "node_modules/eslint-plugin-i18n-json/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "license": "Apache-2.0", + "node_modules/eslint-plugin-i18n-json/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=0.8.0" } }, - "node_modules/eslint/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==", - "license": "MIT" - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/eslint-plugin-i18n-json/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=4" } }, - "node_modules/eslint/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==", + "node_modules/eslint-plugin-i18n-json/node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "chalk": "^2.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint-plugin-i18n-json/node_modules/pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" } }, - "node_modules/eslint/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==", + "node_modules/eslint-plugin-i18n-json/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/eslint/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==", - "license": "MIT" - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/eslint-plugin-unused-imports": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", + "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } } }, - "node_modules/eslint/node_modules/eslint-scope": { + "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", @@ -10671,77 +9704,60 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/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==", - "license": "MIT", - "engines": { - "node": ">=8" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/eslint/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==", - "license": "MIT", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, "node_modules/espree": { @@ -10929,9 +9945,9 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "license": "MIT", "dependencies": { @@ -10954,7 +9970,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -10969,6 +9985,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/debug": { @@ -10988,6 +10008,22 @@ "dev": true, "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -11176,6 +10212,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -11198,16 +10244,6 @@ "minimatch": "^5.0.1" } }, - "node_modules/filelist/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/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -11287,17 +10323,19 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -11521,17 +10559,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11627,6 +10670,30 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -11745,13 +10812,13 @@ "peer": true }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11778,44 +10845,18 @@ "license": "MIT" }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -12192,32 +11233,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ignore-walk/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/ignore-walk/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/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -12255,15 +11270,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -12284,6 +11290,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-local/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/import-local/node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -12307,13 +11369,12 @@ } }, "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/inflight": { @@ -12359,13 +11420,6 @@ "node": ">= 12" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -12405,9 +11459,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.0.tgz", + "integrity": "sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g==", "dev": true, "license": "MIT", "dependencies": { @@ -12723,29 +11777,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/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/istanbul-lib-report/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/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -12820,122 +11851,70 @@ "node": ">=10" } }, - "node_modules/jake/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==", + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "*" } }, - "node_modules/jake/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/jake/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==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jake/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/jake/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/jake/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/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-changed-files/node_modules/execa": { @@ -13024,69 +12003,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/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/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-circus/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/jest-circus/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/jest-circus/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/jest-circus/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -13097,19 +12013,6 @@ "node": ">=8" } }, - "node_modules/jest-circus/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/jest-cli": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", @@ -13144,82 +12047,6 @@ } } }, - "node_modules/jest-cli/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/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-cli/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/jest-cli/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/jest-cli/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/jest-cli/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/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -13266,182 +12093,138 @@ } } }, - "node_modules/jest-config/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==", + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jest-config/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=8" } }, - "node_modules/jest-config/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, + "node_modules/jest-diff": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", + "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "chalk": "^2.0.1", + "diff": "^3.2.0", + "jest-get-type": "^22.4.3", + "pretty-format": "^22.4.3" } }, - "node_modules/jest-config/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/jest-config/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/jest-config/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, + "node_modules/jest-diff/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/jest-config/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, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, + "node_modules/jest-diff/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-diff/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, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "color-name": "1.1.3" } }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/jest-diff/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.8.0" } }, - "node_modules/jest-diff/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, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/jest-diff/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, + "node_modules/jest-diff/node_modules/jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", "license": "MIT" }, - "node_modules/jest-diff/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, + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" } }, "node_modules/jest-diff/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, + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/jest-docblock": { @@ -13474,82 +12257,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/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/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-each/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/jest-each/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/jest-each/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/jest-each/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/jest-environment-jsdom": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", @@ -13662,164 +12369,41 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/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==", + "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/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/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/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/jest-message-util/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/jest-message-util/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": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util/node_modules/slash": { @@ -13832,19 +12416,6 @@ "node": ">=8" } }, - "node_modules/jest-message-util/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/jest-mock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", @@ -13879,9 +12450,9 @@ } }, "node_modules/jest-preset-angular": { - "version": "14.3.2", - "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.3.2.tgz", - "integrity": "sha512-Aoei1O/o7x1I6bSCpU08jGqtQ2RBq7HvNbMIo/vHHbM50v4HX1gF3sWZTkM0U0KorNkdwZeONjMsPNwHyUAKqA==", + "version": "14.4.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.4.2.tgz", + "integrity": "sha512-BYYv0FaTDfBNh8WyA9mpOV3krfw20kurBGK8INZUnv7KZDAWZuQtCET4TwTWxSNQ9jS1OX1+a5weCm/bTDDM1A==", "dev": true, "license": "MIT", "dependencies": { @@ -13899,10 +12470,9 @@ "esbuild": ">=0.15.13" }, "peerDependencies": { - "@angular-devkit/build-angular": ">=15.0.0 <19.0.0", - "@angular/compiler-cli": ">=15.0.0 <19.0.0", - "@angular/core": ">=15.0.0 <19.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 <19.0.0", + "@angular/compiler-cli": ">=15.0.0 <20.0.0", + "@angular/core": ">=15.0.0 <20.0.0", + "@angular/platform-browser-dynamic": ">=15.0.0 <20.0.0", "jest": "^29.0.0", "typescript": ">=4.8" } @@ -13952,69 +12522,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve/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/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-resolve/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/jest-resolve/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/jest-resolve/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/jest-resolve/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -14025,19 +12532,6 @@ "node": ">=8" } }, - "node_modules/jest-resolve/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/jest-runner": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", @@ -14071,69 +12565,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner/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/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runner/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/jest-runner/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/jest-runner/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/jest-runner/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -14155,19 +12586,6 @@ "source-map": "^0.6.0" } }, - "node_modules/jest-runner/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/jest-runtime": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", @@ -14202,69 +12620,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/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/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime/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/jest-runtime/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/jest-runtime/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/jest-runtime/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -14275,19 +12630,6 @@ "node": ">=8" } }, - "node_modules/jest-runtime/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/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -14306,404 +12648,132 @@ "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/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/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/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/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/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/jest-util/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/jest-util/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/jest-util/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/jest-util/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/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/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/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-validate/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/jest-validate/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/jest-validate/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", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/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==", + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher": { + "node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher/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==", + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-watcher/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==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=7.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher/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/jest-watcher/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==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-watcher/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==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { @@ -14722,16 +12792,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/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/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -14765,14 +12825,12 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -14858,6 +12916,32 @@ "node": ">= 6" } }, + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsdom/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -15346,16 +13430,18 @@ } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -15418,103 +13504,27 @@ }, "node_modules/lodash.truncate": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/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/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/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/log-symbols/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/log-symbols/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==", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } + "peer": true }, - "node_modules/log-symbols/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==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update": { @@ -15797,6 +13807,16 @@ "tmpl": "1.0.5" } }, + "node_modules/math-intrinsics": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -15827,9 +13847,9 @@ } }, "node_modules/memfs": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.14.0.tgz", - "integrity": "sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.15.0.tgz", + "integrity": "sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -16009,15 +14029,18 @@ "license": "ISC" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -16243,9 +14266,9 @@ "license": "MIT" }, "node_modules/msgpackr": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz", - "integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", + "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", "dev": true, "license": "MIT", "optionalDependencies": { @@ -16300,9 +14323,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -16445,9 +14468,9 @@ } }, "node_modules/node-gyp": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", - "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz", + "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==", "dev": true, "license": "MIT", "dependencies": { @@ -16470,9 +14493,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", - "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dev": true, "license": "MIT", "optional": true, @@ -16497,16 +14520,6 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/node-gyp/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/node-gyp/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -16538,22 +14551,6 @@ "node": ">=16" } }, - "node_modules/node-gyp/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/node-gyp/node_modules/which": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", @@ -16763,16 +14760,16 @@ } }, "node_modules/nwsapi": { - "version": "2.2.13", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true, "license": "MIT" }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, "license": "MIT", "engines": { @@ -16898,86 +14895,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/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/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/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/ora/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/ora/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/ora/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/ordered-binary": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.2.tgz", - "integrity": "sha512-JTo+4+4Fw7FreyAvlSLjb1BBVaxEQAacmjD3jjuyPZclpbEghTvQZbXBb2qPd2LeIMxiHwXBZUcpmG2Gl/mDEA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", + "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", "dev": true, "license": "MIT" }, @@ -17014,29 +14935,15 @@ } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -17059,9 +14966,9 @@ } }, "node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17182,9 +15089,9 @@ } }, "node_modules/parse5": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", - "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "devOptional": true, "license": "MIT", "dependencies": { @@ -17292,9 +15199,9 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, "license": "MIT" }, @@ -17571,14 +15478,14 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", + "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" }, "engines": { @@ -17589,13 +15496,13 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, "license": "ISC", "dependencies": { - "postcss-selector-parser": "^6.0.4" + "postcss-selector-parser": "^7.0.0" }, "engines": { "node": "^10 || ^12 || >= 14" @@ -17683,9 +15590,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17871,11 +15778,17 @@ "optional": true }, "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } }, "node_modules/pump": { "version": "3.0.2", @@ -17915,9 +15828,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", + "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -17993,16 +15906,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -18026,29 +15929,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/reflect-metadata": { @@ -18103,16 +15994,16 @@ "license": "MIT" }, "node_modules/regexpu-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", - "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", - "regjsparser": "^0.11.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -18128,9 +16019,9 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", - "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -18221,7 +16112,7 @@ "node": ">=8" } }, - "node_modules/resolve-from": { + "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", @@ -18231,6 +16122,15 @@ "node": ">=8" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", @@ -18274,9 +16174,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", "engines": { @@ -18347,16 +16247,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/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/rimraf/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -18372,23 +16262,7 @@ "path-scurry": "^1.11.1" }, "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/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" + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -18430,6 +16304,13 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -18562,6 +16443,70 @@ } } }, + "node_modules/sass/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/sass/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sass/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", @@ -18584,9 +16529,9 @@ } }, "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, "license": "MIT", "dependencies": { @@ -18596,7 +16541,7 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -18818,24 +16763,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -18878,26 +16805,86 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -19036,13 +17023,13 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -19194,9 +17181,9 @@ } }, "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true, "license": "BSD-3-Clause" }, @@ -19414,9 +17401,9 @@ } }, "node_modules/stylelint": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", - "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz", + "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==", "dev": true, "funding": [ { @@ -19467,7 +17454,7 @@ "string-width": "^4.2.3", "supports-hyperlinks": "^3.1.0", "svg-tags": "^1.0.0", - "table": "^6.8.2", + "table": "^6.9.0", "write-file-atomic": "^5.0.1" }, "bin": { @@ -19596,44 +17583,6 @@ "stylelint": "^16.0.2" } }, - "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/stylelint/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, "node_modules/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", @@ -19745,19 +17694,15 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/stylelint/node_modules/slash": { @@ -19787,15 +17732,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-hyperlinks": { @@ -19816,31 +17761,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-hyperlinks/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", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/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", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -19890,50 +17810,11 @@ "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/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", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/table/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", - "peer": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/table/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", - "peer": true + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", @@ -20056,17 +17937,17 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", + "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -20090,43 +17971,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -20142,32 +17986,6 @@ "node": ">= 10.13.0" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -20206,6 +18024,30 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/thingies": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", @@ -20244,22 +18086,22 @@ "license": "MIT" }, "node_modules/tldts": { - "version": "6.1.58", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.58.tgz", - "integrity": "sha512-MQJrJhjHOYGYb8DobR6Y4AdDbd4TYkyQ+KBDVc5ODzs1cbrvPpfN1IemYi9jfipJ/vR1YWvrDli0hg1y19VRoA==", + "version": "6.1.68", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.68.tgz", + "integrity": "sha512-JKF17jROiYkjJPT73hUTEiTp2OBCf+kAlB+1novk8i6Q6dWjHsgEjw9VLiipV4KTJavazXhY1QUXyQFSem2T7w==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.58" + "tldts-core": "^6.1.68" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.58", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.58.tgz", - "integrity": "sha512-dR936xmhBm7AeqHIhCWwK765gZ7dFyL+IqLSFAjJbFlUXGMLCb8i2PzlzaOuWBuplBTaBYseSb565nk/ZEM0Bg==", + "version": "6.1.68", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.68.tgz", + "integrity": "sha512-85TdlS/DLW/gVdf2oyyzqp3ocS30WxjaL4la85EArl9cHUR/nizifKAJPziWewSZjDZS71U517/i6ciUeqtB5Q==", "dev": true, "license": "MIT" }, @@ -20303,29 +18145,16 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, "node_modules/tr46": { @@ -20489,66 +18318,228 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.0.tgz", + "integrity": "sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.18.0", + "@typescript-eslint/parser": "8.18.0", + "@typescript-eslint/utils": "8.18.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz", + "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/type-utils": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz", + "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==", + "dev": true, + "license": "MITClause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz", + "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz", + "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz", + "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz", + "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==", "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true, - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "engines": { - "node": ">=14.17" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/typescript-eslint": { + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { "version": "8.18.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.0.tgz", - "integrity": "sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz", + "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.18.0", - "@typescript-eslint/parser": "8.18.0", - "@typescript-eslint/utils": "8.18.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -20562,10 +18553,28 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz", + "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.18.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "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" }, @@ -21323,9 +19332,9 @@ } }, "node_modules/vite/node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -21344,7 +19353,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -21562,6 +19571,44 @@ } } }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", @@ -21587,6 +19634,32 @@ } } }, + "node_modules/webpack-dev-server/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", @@ -21661,6 +19734,30 @@ "ajv": "^6.9.1" } }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/webpack/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -21834,78 +19931,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "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/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/wrap-ansi-cjs/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/wrap-ansi/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/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/wrap-ansi/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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", From b9fa2e3d7a6d3a10a968d23d9e8dde70eab73814 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 19 Dec 2024 11:02:40 +0100 Subject: [PATCH 73/78] clean up eslint config and packages --- frontend/eslint.config.mjs | 6 ------ frontend/package.json | 2 -- 2 files changed, 8 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index c8fad5dbca..077233df23 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -4,7 +4,6 @@ import unusedImports from 'eslint-plugin-unused-imports' import stylistic from '@stylistic/eslint-plugin' import html from '@html-eslint/eslint-plugin' import angular from 'angular-eslint' -import angularTemplateParser from '@angular-eslint/template-parser' import htmlParser from '@html-eslint/parser' export default tsEslint.config( @@ -89,11 +88,6 @@ export default tsEslint.config( files: ['**/*.html'], // recommended configuration included in the plugin ...html.configs['flat/recommended'], - //extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], - //processor: angular.processInlineTemplates, - //languageOptions: { - //parser: angularTemplateParser, - //}, languageOptions: { parser: htmlParser, }, diff --git a/frontend/package.json b/frontend/package.json index 8ea1b91570..a2307db0b7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -72,8 +72,6 @@ "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.4.2", - "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", "typescript-eslint": "8.18.0", "uuid": "^11.0.0" From bd354995679b60be1e670ecf049462f2c7812283 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Thu, 19 Dec 2024 11:19:55 +0100 Subject: [PATCH 74/78] change formatting dependencies to dev dep and regen package-lock --- frontend/package-lock.json | 1422 ++++++------------------------------ frontend/package.json | 5 +- 2 files changed, 208 insertions(+), 1219 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 27f1fcdc2b..e35687a7ae 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,11 +21,8 @@ "@angular/router": "^18.2.8", "@ngx-translate/core": "^16.0.0", "@ngx-translate/http-loader": "^16.0.0", - "@stylistic/eslint-plugin": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", - "eslint-plugin-i18n-json": "^4.0.0", "moment": "^2.30.1", "ngx-toastr": "^19.0.0", "rxjs": "^7.8.1", @@ -40,9 +37,11 @@ "@eslint/js": "^9.15.0", "@html-eslint/eslint-plugin": "^0.27.0", "@html-eslint/parser": "^0.27.0", + "@stylistic/eslint-plugin": "^2.11.0", "@types/eslint__js": "^8.42.3", "@types/jest": "^29.5.13", "@types/uuid": "^10.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-eslint": "19.0.2", "browserslist": "^4.24.2", "cypress": "^13.15.0", @@ -53,8 +52,6 @@ "jest-preset-angular": "^14.2.4", "ngx-translate-testing": "^7.0.0", "prettier": "^3.4.2", - "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-config-standard-scss": "^14.0.0", "typescript": "^5.5.4", "typescript-eslint": "8.18.0", "uuid": "^11.0.0" @@ -313,13 +310,13 @@ } }, "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/architect": { - "version": "0.1900.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.5.tgz", - "integrity": "sha512-JxgoIxwGw3QNj6e70d04g5yJ8ZK0g/my22UK0TlRJRbYcfFQr8pL7u3wq77iNlgeHMDwBskZEf4TEZOVSbm7mw==", + "version": "0.1900.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.6.tgz", + "integrity": "sha512-w11bAXQnNWBawTJfQPjvaTRrzrqsOUm9tK9WNvaia/xjiRFpmO0CfmKtn3axNSEJM8jb/czaNQrgTwG+TGc/8g==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.5", + "@angular-devkit/core": "19.0.6", "rxjs": "7.8.1" }, "engines": { @@ -329,9 +326,9 @@ } }, "node_modules/@angular-eslint/builder/node_modules/@angular-devkit/core": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", - "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", + "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", "dev": true, "license": "MIT", "dependencies": { @@ -415,9 +412,9 @@ } }, "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/core": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", - "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", + "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", "dev": true, "license": "MIT", "dependencies": { @@ -443,13 +440,13 @@ } }, "node_modules/@angular-eslint/schematics/node_modules/@angular-devkit/schematics": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.5.tgz", - "integrity": "sha512-dhLVBVb0ECfcIP59azoD/5lJMSMU//bo1LEbuE0VrFA9orVxQhgilNuZeVXBr5sOll1PFjxs/fqyX8sAH9xQYw==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.6.tgz", + "integrity": "sha512-R9hlHfAh1HKoIWgnYJlOEKhUezhTNl0fpUmHxG2252JSY5FLRxmYArTtJYYmbNdBbsBLNg3UHyM/GBPvJSA3NQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.5", + "@angular-devkit/core": "19.0.6", "jsonc-parser": "3.3.1", "magic-string": "0.30.12", "ora": "5.4.1", @@ -839,6 +836,7 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -1225,6 +1223,7 @@ "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" @@ -2790,100 +2789,6 @@ "node": ">=0.1.90" } }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", - "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, "node_modules/@cypress/request": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", @@ -2997,18 +2902,6 @@ "node": ">=14.17.0" } }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", @@ -3421,6 +3314,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -3439,6 +3333,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3451,6 +3346,7 @@ "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -3460,6 +3356,7 @@ "version": "0.19.1", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.5", @@ -3474,6 +3371,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3484,6 +3382,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -3496,6 +3395,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -3508,6 +3408,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -3531,6 +3432,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -3547,6 +3449,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3557,6 +3460,7 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -3569,12 +3473,14 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -3587,6 +3493,7 @@ "version": "9.17.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3596,6 +3503,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3605,6 +3513,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "dev": true, "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" @@ -3613,57 +3522,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@formatjs/ecma402-abstract": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.1.tgz", - "integrity": "sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw==", - "license": "MIT", - "dependencies": { - "@formatjs/fast-memoize": "2.2.5", - "@formatjs/intl-localematcher": "0.5.9", - "decimal.js": "10", - "tslib": "2" - } - }, - "node_modules/@formatjs/fast-memoize": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.5.tgz", - "integrity": "sha512-6PoewUMrrcqxSoBXAOJDiW1m+AmkrAj0RiXnOMD59GRaswjXhm3MDhgepXPBgonc09oSirAJTsAggzAGQf6A6g==", - "license": "MIT", - "dependencies": { - "tslib": "2" - } - }, - "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.9.7", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.7.tgz", - "integrity": "sha512-cuEHyRM5VqLQobANOjtjlgU7+qmk9Q3fDQuBiRRJ3+Wp3ZoZhpUPtUfuimZXsir6SaI2TaAJ+SLo9vLnV5QcbA==", - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.3.1", - "@formatjs/icu-skeleton-parser": "1.8.11", - "tslib": "2" - } - }, - "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.11.tgz", - "integrity": "sha512-8LlHHE/yL/zVJZHAX3pbKaCjZKmBIO6aJY1mkVh4RMSEu/2WRZ4Ysvv3kKXJ9M8RJLBHdnk1/dUQFdod1Dt7Dw==", - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.3.1", - "tslib": "2" - } - }, - "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.9.tgz", - "integrity": "sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA==", - "license": "MIT", - "dependencies": { - "tslib": "2" - } - }, "node_modules/@html-eslint/eslint-plugin": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.27.0.tgz", @@ -3691,6 +3549,7 @@ "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18.0" @@ -3700,6 +3559,7 @@ "version": "0.16.6", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", @@ -3713,6 +3573,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -3726,6 +3587,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" @@ -3739,6 +3601,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -4904,9 +4767,9 @@ } }, "node_modules/@ngx-translate/core": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-16.0.3.tgz", - "integrity": "sha512-UPse66z9tRUmIpeorYodXBQY6O4foUmj9jy9cCuuja7lqdOwRBWPzCWqc+qYIXv5L2QoqZdxgHtqoUz+Q9weSA==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-16.0.4.tgz", + "integrity": "sha512-s8llTL2SJvROhqttxvEs7Cg+6qSf4kvZPFYO+cTOY1d8DWTjlutRkWAleZcPPoeX927Dm7ALfL07G7oYDJ7z6w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -4917,9 +4780,9 @@ } }, "node_modules/@ngx-translate/http-loader": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-16.0.0.tgz", - "integrity": "sha512-l3okOHGVxZ1Bm55OpakSfXvI2yYmVmhYqgwGU4aIQIRUqpkBCrSDZnmrHTcZfsGJzXKB5E2D2rko9i28gBijmA==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-16.0.1.tgz", + "integrity": "sha512-xJEOUpvs6Zfc8G4cmQmegFOEpfYSoplTHHoisPNrATXjRBjpaKsBaPOXlZsuFUW2XV00s16gIyI4+9z1XkO5bw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -4933,6 +4796,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -4946,6 +4810,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -4955,6 +4820,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -5616,6 +5482,7 @@ "version": "2.12.1", "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz", "integrity": "sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^8.13.0", @@ -5777,6 +5644,7 @@ "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/express": { @@ -5899,6 +5767,7 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, "license": "MIT" }, "node_modules/@types/mime": { @@ -6086,6 +5955,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz", "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==", + "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", @@ -6115,6 +5985,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz", "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -6140,6 +6011,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.18.1", @@ -6157,6 +6029,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz", "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "8.18.1", @@ -6180,6 +6053,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", + "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6193,6 +6067,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.18.1", @@ -6219,6 +6094,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", + "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -6242,6 +6118,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", + "dev": true, "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.18.1", @@ -6496,6 +6373,7 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -6529,6 +6407,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -6600,16 +6479,6 @@ "node": ">=8" } }, - "node_modules/aggregate-error/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -6682,9 +6551,9 @@ } }, "node_modules/angular-eslint/node_modules/@angular-devkit/core": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.5.tgz", - "integrity": "sha512-njBblpYHmlDI+Jtbub9NEm9RH+SBIFmmsgL9uJB8GxQVSo2qo4+f69nTkijRNN8WNKsSkYoRR9+JSl9QXWbyEA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", + "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", "dev": true, "license": "MIT", "dependencies": { @@ -6710,13 +6579,13 @@ } }, "node_modules/angular-eslint/node_modules/@angular-devkit/schematics": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.5.tgz", - "integrity": "sha512-dhLVBVb0ECfcIP59azoD/5lJMSMU//bo1LEbuE0VrFA9orVxQhgilNuZeVXBr5sOll1PFjxs/fqyX8sAH9xQYw==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.6.tgz", + "integrity": "sha512-R9hlHfAh1HKoIWgnYJlOEKhUezhTNl0fpUmHxG2252JSY5FLRxmYArTtJYYmbNdBbsBLNg3UHyM/GBPvJSA3NQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.0.5", + "@angular-devkit/core": "19.0.6", "jsonc-parser": "3.3.1", "magic-string": "0.30.12", "ora": "5.4.1", @@ -6804,6 +6673,7 @@ "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" @@ -6867,6 +6737,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, "license": "Python-2.0" }, "node_modules/aria-query": { @@ -6886,17 +6757,6 @@ "dev": true, "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -7226,6 +7086,7 @@ "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/base64-js": { @@ -7414,6 +7275,7 @@ "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" @@ -7423,6 +7285,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -7652,6 +7515,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7668,9 +7532,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001689", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", - "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "dev": true, "funding": [ { @@ -7699,6 +7563,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -7739,9 +7604,9 @@ } }, "node_modules/chokidar": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.2.tgz", - "integrity": "sha512-/b57FK+bblSU+dfewfFe0rT1YjVDfOmeLQwCAuC+vwvgLkXboATqqmy+Ipux6JrF6L5joe5CBnFOw+gLWH6yKg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { @@ -8023,6 +7888,7 @@ "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" @@ -8035,15 +7901,8 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", @@ -8145,6 +8004,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, "node_modules/connect-history-api-fallback": { @@ -8333,6 +8193,7 @@ "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", @@ -8343,17 +8204,6 @@ "node": ">= 8" } }, - "node_modules/css-functions-list": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", - "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12 || >=16" - } - }, "node_modules/css-loader": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", @@ -8407,20 +8257,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -8723,6 +8559,7 @@ "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" @@ -8740,6 +8577,7 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, "license": "MIT" }, "node_modules/dedent": { @@ -8761,6 +8599,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, "node_modules/deepmerge": { @@ -8954,15 +8793,6 @@ "dev": true, "license": "MIT" }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -8973,31 +8803,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -9318,6 +9123,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -9444,6 +9250,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9489,6 +9296,7 @@ "version": "9.17.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -9544,154 +9352,27 @@ } } }, - "node_modules/eslint-plugin-i18n-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-i18n-json/-/eslint-plugin-i18n-json-4.0.0.tgz", - "integrity": "sha512-rglbr9f/UaPN/OeiSLVVFlIh4RrXPTzX5qr4tqOdTj1Ryr8xIhUzriDDuyuPWliektO86c/zy1RldmBIOfDNsQ==", - "license": "MIT", - "dependencies": { - "@formatjs/icu-messageformat-parser": "^2.0.18", - "chalk": "^2.3.2", - "indent-string": "^3.2.0", - "jest-diff": "^22.0.3", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "lodash.isplainobject": "^4.0.6", - "lodash.set": "^4.3.2", - "log-symbols": "^2.2.0", - "parse-json": "^5.2.0", - "plur": "^2.1.2", - "pretty-format": "^22.0.3" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=4.0.0" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/eslint-plugin-unused-imports": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", + "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", + "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, - "node_modules/eslint-plugin-i18n-json/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "license": "MIT", - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/pretty-format": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", - "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - } - }, - "node_modules/eslint-plugin-i18n-json/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", - "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^9.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } } }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -9708,6 +9389,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9720,6 +9402,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -9736,6 +9419,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9746,12 +9430,14 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -9764,6 +9450,7 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.14.0", @@ -9795,6 +9482,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -9807,6 +9495,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -9819,6 +9508,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -9828,6 +9518,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -10094,12 +9785,14 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -10116,6 +9809,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -10128,12 +9822,14 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, "license": "MIT" }, "node_modules/fast-uri": { @@ -10143,21 +9839,11 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4.9.1" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -10226,6 +9912,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" @@ -10261,6 +9948,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -10326,6 +10014,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -10352,6 +10041,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -10365,6 +10055,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { @@ -10655,6 +10346,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -10720,58 +10412,6 @@ "node": ">=10" } }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -10803,14 +10443,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -10835,6 +10467,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, "license": "MIT" }, "node_modules/handle-thing": { @@ -10848,6 +10481,7 @@ "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" @@ -10982,20 +10616,6 @@ "dev": true, "license": "MIT" }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -11215,6 +10835,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -11258,6 +10879,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -11363,18 +10985,20 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/inflight": { @@ -11430,19 +11054,11 @@ "node": ">= 10" } }, - "node_modules/irregular-plurals": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", - "integrity": "sha512-kniTIJmaZYiwa17eTtWIfm0K342seyugl6vuC8DiiyiRAJWAVlLkqGCI0Im0neo0TkXw+pRcKaBPRdcKHnQJ6Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, "license": "MIT" }, "node_modules/is-binary-path": { @@ -11494,6 +11110,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11526,6 +11143,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -11604,6 +11222,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -11716,6 +11335,7 @@ "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/isobject": { @@ -12120,111 +11740,19 @@ } }, "node_modules/jest-diff": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", - "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", - "license": "MIT", - "dependencies": { - "chalk": "^2.0.1", - "diff": "^3.2.0", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" - } - }, - "node_modules/jest-diff/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, - "node_modules/jest-diff/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-diff/node_modules/jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "license": "MIT" - }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", - "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { @@ -12369,22 +11897,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-message-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", @@ -12662,31 +12174,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/jest-diff": { + "node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", + "@jest/types": "^29.6.3", + "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", @@ -12809,10 +12305,10 @@ } }, "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "devOptional": true, + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -12822,12 +12318,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -12959,6 +12457,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -12989,6 +12488,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "license": "MIT" }, "node_modules/json-stringify-safe": { @@ -13071,6 +12571,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -13096,13 +12597,6 @@ "node": ">=6" } }, - "node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", - "dev": true, - "license": "MIT" - }, "node_modules/launch-editor": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", @@ -13240,6 +12734,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -13271,6 +12766,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, "license": "MIT" }, "node_modules/listr2": { @@ -13433,6 +12929,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -13458,24 +12955,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -13487,6 +12966,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, "license": "MIT" }, "node_modules/lodash.once": { @@ -13496,20 +12976,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", - "license": "MIT" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -13808,34 +13274,15 @@ } }, "node_modules/math-intrinsics": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", - "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -13866,20 +13313,6 @@ "url": "https://github.com/sponsors/streamich" } }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -13901,6 +13334,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -13920,6 +13354,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -13933,6 +13368,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -14032,6 +13468,7 @@ "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" @@ -14263,6 +13700,7 @@ "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/msgpackr": { @@ -14345,6 +13783,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, "license": "MIT" }, "node_modules/needle": { @@ -14858,6 +14297,7 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -14923,6 +14363,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -14938,6 +14379,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -15046,6 +14488,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -15058,6 +14501,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -15076,6 +14520,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, "node_modules/parse-node-version": { @@ -15143,6 +14588,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -15162,6 +14608,7 @@ "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" @@ -15236,12 +14683,14 @@ "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" @@ -15384,18 +14833,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/plur": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", - "integrity": "sha512-WhcHk576xg9y/iv6RWOuroZgsqvCbJN+XGvAypCJwLAYs2iWDp5LUmvaCdV6JR2O0SMBf8l6p7A94AyLCFVMlQ==", - "license": "MIT", - "dependencies": { - "irregular-plurals": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/postcss": { "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", @@ -15527,68 +14964,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-scss": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-scss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.4.29" - } - }, "node_modules/postcss-selector-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", @@ -15614,6 +14989,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -15805,6 +15181,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -15854,6 +15231,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -16126,6 +15504,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -16218,6 +15597,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -16328,6 +15708,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -16591,6 +15972,7 @@ "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" @@ -16787,6 +16169,7 @@ "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" @@ -16799,6 +16182,7 @@ "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" @@ -17392,349 +16776,20 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylelint": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz", - "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", - "css-tree": "^3.0.1", - "debug": "^4.3.7", - "fast-glob": "^3.3.2", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^9.1.0", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^6.0.2", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.35.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.49", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.1.0", - "svg-tags": "^1.0.0", - "table": "^6.9.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/stylelint-config-recommended": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", - "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.1.0" - } - }, - "node_modules/stylelint-config-recommended-scss": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", - "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-scss": "^4.0.9", - "stylelint-config-recommended": "^14.0.1", - "stylelint-scss": "^6.4.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.6.1" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/stylelint-config-standard": { - "version": "36.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", - "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "dependencies": { - "stylelint-config-recommended": "^14.0.1" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.1.0" - } - }, - "node_modules/stylelint-config-standard-scss": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-14.0.0.tgz", - "integrity": "sha512-6Pa26D9mHyi4LauJ83ls3ELqCglU6VfCXchovbEqQUiEkezvKdv6VgsIoMy58i00c854wVmOw0k8W5FTpuaVqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "stylelint-config-recommended-scss": "^14.1.0", - "stylelint-config-standard": "^36.0.1" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.11.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/stylelint-scss": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.10.0.tgz", - "integrity": "sha512-y03if6Qw9xBMoVaf7tzp5BbnYhYvudIKzURkhSHzcHG0bW0fAYvQpTUVJOe7DyhHaxeThBil4ObEMvGbV7+M+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-tree": "^3.0.1", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.35.0", - "mdn-data": "^2.12.2", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.0.2" - } - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", - "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flat-cache": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", - "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flatted": "^3.3.1", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/stylelint/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/globby/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/stylelint/node_modules/ignore": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", - "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/stylelint/node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "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", - "peer": true, - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "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" @@ -17743,24 +16798,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", - "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -17774,13 +16811,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true, - "peer": true - }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -17798,54 +16828,6 @@ "dev": true, "license": "MIT" }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/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", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -18126,6 +17108,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -18201,6 +17184,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -18303,6 +17287,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -18359,6 +17344,7 @@ "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -18726,6 +17712,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -19870,6 +18857,7 @@ "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" @@ -19892,6 +18880,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -20059,6 +19048,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/frontend/package.json b/frontend/package.json index a2307db0b7..3e183315ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -40,11 +40,8 @@ "@angular/router": "^18.2.8", "@ngx-translate/core": "^16.0.0", "@ngx-translate/http-loader": "^16.0.0", - "@stylistic/eslint-plugin": "^2.11.0", - "@typescript-eslint/eslint-plugin": "^8.15.0", "angular-oauth2-oidc": "^17.0.2", "bootstrap": "^5.3.3", - "eslint-plugin-i18n-json": "^4.0.0", "moment": "^2.30.1", "ngx-toastr": "^19.0.0", "rxjs": "^7.8.1", @@ -56,6 +53,8 @@ "@angular/compiler-cli": "^18.2.8", "@cypress/schematic": "^2.5.2", "@cypress/skip-test": "^2.6.1", + "@stylistic/eslint-plugin": "^2.11.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", "@eslint/js": "^9.15.0", "@html-eslint/eslint-plugin": "^0.27.0", "@html-eslint/parser": "^0.27.0", From 7de2ef592970d24f786b3350cb30cc9957dc924d Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 20 Dec 2024 11:18:30 +0100 Subject: [PATCH 75/78] update formatter --- backend/src/main/resources/formatting.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/src/main/resources/formatting.xml b/backend/src/main/resources/formatting.xml index 28875c862f..1dfa52c2c2 100644 --- a/backend/src/main/resources/formatting.xml +++ b/backend/src/main/resources/formatting.xml @@ -90,15 +90,15 @@ - - - - - - - - - + + + + + + + + + From 7d457b73a0906c5b7dc2165e0219217651b80143 Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 20 Dec 2024 12:35:18 +0100 Subject: [PATCH 76/78] update frontend formatter --- frontend/eslint.config.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 077233df23..b3cb6e20bf 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -55,7 +55,10 @@ export default tsEslint.config( '@stylistic/object-curly-spacing': ['error', 'always'], '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], '@stylistic/semi-style': ['error'], + "space-before-function-paren": ["error", "always"], '@stylistic/function-paren-newline': ['error', { minItems: 4 }], + " @stylistic/space-before-function-paren": ["error", "never"], + '@angular-eslint/directive-selector': [ 'error', { From 8378a80bdbebc64ef66a28ce2a00ca9539d8799f Mon Sep 17 00:00:00 2001 From: Yanick Minder Date: Fri, 20 Dec 2024 12:44:09 +0100 Subject: [PATCH 77/78] update formatter --- frontend/eslint.config.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index b3cb6e20bf..0929c9d4c0 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -55,9 +55,9 @@ export default tsEslint.config( '@stylistic/object-curly-spacing': ['error', 'always'], '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], '@stylistic/semi-style': ['error'], - "space-before-function-paren": ["error", "always"], + "space-before-function-paren": ["error", "never"], '@stylistic/function-paren-newline': ['error', { minItems: 4 }], - " @stylistic/space-before-function-paren": ["error", "never"], + "@stylistic/space-before-function-paren": ["error", "never"], '@angular-eslint/directive-selector': [ 'error', From 77344505d337490933144dc7b4591ddec4ec7cea Mon Sep 17 00:00:00 2001 From: Jannik Pulfer <109959802+RandomTannenbaum@users.noreply.github.com> Date: Fri, 20 Dec 2024 13:06:10 +0100 Subject: [PATCH 78/78] Feature/1135 Apply Formatters (#1221) * run frontend formatter * run backend formatter * update package-lock * apply formatter * run formatter * run prettier --------- Co-authored-by: Yanick Minder --- .../main/java/ch/puzzle/okr/Constants.java | 17 +- .../src/main/java/ch/puzzle/okr/ErrorKey.java | 22 +- .../java/ch/puzzle/okr/ForwardFilter.java | 5 +- .../ch/puzzle/okr/OkrErrorAttributes.java | 3 +- .../ch/puzzle/okr/OpenAPI30Configuration.java | 12 +- .../java/ch/puzzle/okr/SecurityConfig.java | 56 +-- .../java/ch/puzzle/okr/UserKeyGenerator.java | 3 +- .../okr/controller/ActionController.java | 7 +- .../okr/controller/AlignmentController.java | 18 +- .../okr/controller/CheckInController.java | 16 +- .../controller/ClientConfigController.java | 3 +- .../okr/controller/CompletedController.java | 2 +- .../okr/controller/KeyResultController.java | 27 +- .../okr/controller/ObjectiveController.java | 54 ++- .../okr/controller/OverviewController.java | 19 +- .../okr/controller/QuarterController.java | 4 +- .../puzzle/okr/controller/TeamController.java | 38 +- .../puzzle/okr/controller/UserController.java | 22 +- .../okr/deserializer/CheckInDeserializer.java | 9 +- .../okr/deserializer/DeserializerHelper.java | 8 +- .../deserializer/KeyResultDeserializer.java | 5 +- .../puzzle/okr/dto/DuplicateObjectiveDto.java | 1 - .../main/java/ch/puzzle/okr/dto/ErrorDto.java | 1 - .../java/ch/puzzle/okr/dto/ObjectiveDto.java | 1 - .../okr/dto/checkin/CheckInMetricDto.java | 5 +- .../okr/dto/checkin/CheckInOrdinalDto.java | 5 +- .../okr/dto/keyresult/KeyResultDto.java | 1 - .../KeyResultLastCheckInOrdinalDto.java | 1 - .../okr/dto/keyresult/KeyResultMetricDto.java | 1 - .../dto/keyresult/KeyResultOrdinalDto.java | 1 - .../overview/OverviewKeyResultOrdinalDto.java | 4 +- .../OverviewLastCheckInMetricDto.java | 4 +- .../OverviewLastCheckInOrdinalDto.java | 4 +- .../dto/overview/OverviewObjectiveDto.java | 1 - .../exception/OkrResponseStatusException.java | 7 +- .../ch/puzzle/okr/mapper/ActionMapper.java | 27 +- .../okr/mapper/AlignmentSelectionMapper.java | 15 +- .../ch/puzzle/okr/mapper/CompletedMapper.java | 9 +- .../ch/puzzle/okr/mapper/ObjectiveMapper.java | 35 +- .../ch/puzzle/okr/mapper/OverviewMapper.java | 62 ++- .../java/ch/puzzle/okr/mapper/TeamMapper.java | 6 +- .../java/ch/puzzle/okr/mapper/UserMapper.java | 21 +- .../puzzle/okr/mapper/UserOkrDataMapper.java | 12 +- .../okr/mapper/checkin/CheckInMapper.java | 8 +- .../mapper/checkin/CheckInMetricMapper.java | 21 +- .../mapper/checkin/CheckInOrdinalMapper.java | 22 +- .../okr/mapper/keyresult/KeyResultMapper.java | 15 +- .../keyresult/KeyResultMetricMapper.java | 69 +-- .../keyresult/KeyResultOrdinalMapper.java | 70 +-- .../java/ch/puzzle/okr/models/Action.java | 7 +- .../java/ch/puzzle/okr/models/Completed.java | 4 +- .../java/ch/puzzle/okr/models/Objective.java | 31 +- .../java/ch/puzzle/okr/models/Quarter.java | 5 +- .../main/java/ch/puzzle/okr/models/State.java | 5 +- .../main/java/ch/puzzle/okr/models/Team.java | 3 +- .../main/java/ch/puzzle/okr/models/Unit.java | 6 +- .../main/java/ch/puzzle/okr/models/User.java | 7 +- .../java/ch/puzzle/okr/models/UserTeam.java | 5 +- .../okr/models/alignment/Alignment.java | 3 +- .../models/alignment/AlignmentSelection.java | 17 +- .../alignment/AlignmentSelectionId.java | 1 - .../models/alignment/KeyResultAlignment.java | 1 - .../models/alignment/ObjectiveAlignment.java | 1 - .../authorization/AuthorizationUser.java | 5 +- .../ch/puzzle/okr/models/checkin/CheckIn.java | 29 +- .../okr/models/checkin/CheckInMetric.java | 5 +- .../okr/models/checkin/CheckInOrdinal.java | 5 +- .../ch/puzzle/okr/models/checkin/Zone.java | 5 +- .../okr/models/keyresult/KeyResult.java | 30 +- .../okr/models/keyresult/KeyResultMetric.java | 11 +- .../models/keyresult/KeyResultOrdinal.java | 11 +- .../keyresult/KeyResultWithActionList.java | 1 - .../puzzle/okr/models/overview/Overview.java | 19 +- .../okr/models/overview/OverviewId.java | 5 +- ...FlywayMultitenantMigrationInitializer.java | 10 +- .../okr/multitenancy/HibernateContext.java | 3 +- .../SchemaMultiTenantConnectionProvider.java | 26 +- .../multitenancy/TenantConfigProvider.java | 64 ++- .../okr/multitenancy/TenantContext.java | 3 +- .../TenantClientCustomizationProvider.java | 52 +- .../okr/repository/ActionRepository.java | 3 +- .../okr/repository/AlignmentRepository.java | 3 +- .../AlignmentSelectionRepository.java | 5 +- .../okr/repository/CheckInRepository.java | 3 +- .../okr/repository/KeyResultRepository.java | 3 +- .../okr/repository/ObjectiveRepository.java | 3 +- .../okr/repository/QuarterRepository.java | 5 +- .../puzzle/okr/repository/TeamRepository.java | 3 +- .../puzzle/okr/repository/UserRepository.java | 3 +- .../ch/puzzle/okr/security/JwtHelper.java | 62 +-- .../okr/security/TenantJWSKeySelector.java | 12 +- .../security/TenantJwtIssuerValidator.java | 8 +- .../okr/security/helper/ClaimHelper.java | 9 +- .../okr/security/helper/JwtStatusLogger.java | 25 +- .../okr/security/helper/TokenHelper.java | 7 +- .../ch/puzzle/okr/service/CacheService.java | 4 +- .../ActionAuthorizationService.java | 5 +- .../AuthorizationRegistrationService.java | 6 +- .../authorization/AuthorizationService.java | 120 +++-- .../AuthorizationServiceBase.java | 2 +- .../CheckInAuthorizationService.java | 2 +- .../CompletedAuthorizationService.java | 2 +- .../KeyResultAuthorizationService.java | 12 +- .../ObjectiveAuthorizationService.java | 6 +- .../OverviewAuthorizationService.java | 19 +- .../TeamAuthorizationService.java | 11 +- .../UserAuthorizationService.java | 25 +- .../business/ActionBusinessService.java | 3 +- .../business/AlignmentBusinessService.java | 5 +- .../AlignmentSelectionBusinessService.java | 10 +- .../business/CheckInBusinessService.java | 5 +- .../business/CompletedBusinessService.java | 2 +- .../business/KeyResultBusinessService.java | 27 +- .../business/ObjectiveBusinessService.java | 36 +- .../business/OverviewBusinessService.java | 11 +- .../business/QuarterBusinessService.java | 33 +- .../service/business/TeamBusinessService.java | 36 +- .../service/business/UserBusinessService.java | 14 +- .../clientconfig/ClientConfigService.java | 43 +- .../persistence/ActionPersistenceService.java | 7 +- .../AlignmentPersistenceService.java | 7 +- .../AlignmentSelectionPersistenceService.java | 3 +- .../persistence/AuthorizationCriteria.java | 28 +- .../CheckInPersistenceService.java | 7 +- .../CompletedPersistenceService.java | 4 +- .../KeyResultPersistenceService.java | 10 +- .../ObjectivePersistenceService.java | 22 +- .../OverviewPersistenceService.java | 9 +- .../service/persistence/PersistenceBase.java | 23 +- .../QuarterPersistenceService.java | 7 +- .../persistence/TeamPersistenceService.java | 7 +- .../persistence/UserPersistenceService.java | 7 +- .../UserTeamPersistenceService.java | 7 +- .../validation/ActionValidationService.java | 17 +- .../AlignmentValidationService.java | 3 +- .../validation/CheckInValidationService.java | 13 +- .../CompletedValidationService.java | 3 +- .../KeyResultValidationService.java | 13 +- .../ObjectiveValidationService.java | 40 +- .../validation/OverviewValidationService.java | 2 +- .../validation/QuarterValidationService.java | 30 +- .../validation/TeamValidationService.java | 22 +- .../validation/UserValidationService.java | 4 +- .../service/validation/ValidationBase.java | 29 +- .../util/quarter/generate/QuarterData.java | 12 +- .../util/quarter/generate/QuarterLabel.java | 12 +- .../okr/util/quarter/generate/Quarters.java | 6 +- .../quarter/generate/h2/QuarterFunction.java | 10 +- .../java/ch/puzzle/okr/ForwardFilterTest.java | 8 +- .../puzzle/okr/SpringCachingConfigTest.java | 14 +- .../ch/puzzle/okr/UserKeyGeneratorTest.java | 7 +- .../okr/architecture/OkrArchitectureTest.java | 164 +++++-- .../okr/controller/ActionControllerIT.java | 48 +- .../okr/controller/AlignmentControllerIT.java | 113 +++-- .../okr/controller/CacheControllerIT.java | 16 +- .../okr/controller/CheckInControllerIT.java | 110 +++-- .../controller/ClientConfigControllerIT.java | 28 +- .../okr/controller/CompletedControllerIT.java | 46 +- .../okr/controller/KeyResultControllerIT.java | 233 ++++++--- .../okr/controller/ObjectiveControllerIT.java | 222 ++++++--- .../okr/controller/OverviewControllerIT.java | 181 ++++--- .../okr/controller/QuarterControllerIT.java | 64 ++- .../okr/controller/TeamControllerIT.java | 120 +++-- .../okr/controller/UserControllerIT.java | 97 ++-- .../deserializer/CheckInDeserializerTest.java | 27 +- .../deserializer/DeserializerHelperTest.java | 13 +- .../KeyResultDeserializerTest.java | 21 +- .../puzzle/okr/mapper/ActionMapperTest.java | 29 +- .../mapper/AlignmentSelectionMapperTest.java | 129 +++-- .../okr/mapper/CompletedMapperTest.java | 20 +- .../okr/mapper/ObjectiveMapperTest.java | 17 +- .../puzzle/okr/mapper/OverviewMapperTest.java | 247 +++++++--- .../ch/puzzle/okr/mapper/TeamMapperTest.java | 7 +- .../ch/puzzle/okr/mapper/UserMapperTest.java | 23 +- .../okr/mapper/checkin/CheckInMapperTest.java | 16 +- .../checkin/CheckInMetricMapperTest.java | 14 +- .../checkin/CheckInOrdinalMapperTest.java | 14 +- .../mapper/checkin/helper/AssertHelper.java | 6 +- .../checkin/helper/TestDataConstants.java | 1 - .../checkin/helper/TestDataDtoHelper.java | 40 +- .../mapper/checkin/helper/TestDataHelper.java | 16 +- .../mapper/keyresult/KeyResultMapperTest.java | 41 +- .../keyresult/KeyResultMetricMapperTest.java | 23 +- .../keyresult/KeyResultOrdinalMapperTest.java | 23 +- .../mapper/keyresult/helper/AssertHelper.java | 30 +- .../keyresult/helper/TestDataConstants.java | 1 - .../keyresult/helper/TestDataDtoHelper.java | 119 ++--- .../keyresult/helper/TestDataHelper.java | 37 +- .../authorization/AuthorizationUserTest.java | 21 +- .../okr/models/keyresult/KeyResultTest.java | 12 +- ...rrentTenantIdentifierResolverImplTest.java | 6 +- ...ayMultitenantMigrationInitializerTest.java | 51 +- .../multitenancy/HibernateContextTest.java | 38 +- ...TenantConnectionProviderInternalsTest.java | 7 +- ...hemaMultiTenantConnectionProviderTest.java | 13 +- .../TenantConfigProviderTestIT.java | 15 +- ...TenantClientCustomizationProviderTest.java | 14 +- ...nantClientCustomizationProviderTestIT.java | 16 +- .../security/AuthenticationEventsTest.java | 10 +- .../ch/puzzle/okr/security/JwtHelperTest.java | 72 +-- .../security/TenantJWSKeySelectorTest.java | 18 +- .../TenantJwtIssuerValidatorTest.java | 33 +- .../okr/security/helper/ClaimHelperTest.java | 19 +- .../okr/security/helper/TokenHelperTest.java | 17 +- .../okr/security/helper/UrlHelperTest.java | 7 +- .../ActionAuthorizationServiceTest.java | 52 +- .../AuthorizationRegistrationServiceIT.java | 41 +- .../AuthorizationServiceTest.java | 166 ++++--- .../CheckInAuthorizationServiceTest.java | 35 +- .../CompletedAuthorizationServiceTest.java | 33 +- .../KeyResultAuthorizationServiceTest.java | 55 ++- .../ObjectiveAuthorizationServiceTest.java | 74 +-- .../OverviewAuthorizationServiceTest.java | 32 +- .../TeamAuthorizationServiceTest.java | 40 +- .../UserAuthorizationServiceTest.java | 15 +- .../authorization/UserUpdateHelperTest.java | 24 +- .../business/ActionBusinessServiceTest.java | 81 +++- .../AlignmentBusinessServiceTest.java | 42 +- ...AlignmentSelectionBusinessServiceTest.java | 24 +- .../business/CheckInBusinessServiceTest.java | 60 ++- .../CompletedBusinessServiceTest.java | 38 +- .../business/KeyResultBusinessServiceIT.java | 118 +++-- .../KeyResultBusinessServiceTest.java | 155 ++++-- .../ObjectiveBusinessServiceTest.java | 135 ++++-- .../business/OverviewBusinessServiceTest.java | 140 ++++-- .../business/QuarterBusinessServiceTest.java | 105 ++-- .../business/TeamBusinessServiceTest.java | 83 +++- .../business/UserBusinessServiceTest.java | 65 ++- .../clientconfig/ClientConfigServiceIT.java | 20 +- .../clientconfig/ClientConfigServiceTest.java | 48 +- .../ActionPersistenceServiceIT.java | 31 +- .../AlignmentPersistenceServiceIT.java | 30 +- ...lignmentSelectionPersistenceServiceIT.java | 43 +- .../persistence/AuthorizationCriteriaIT.java | 23 +- .../AuthorizationCriteriaParametersTest.java | 101 ++-- .../AuthorizationCriteriaTest.java | 39 +- .../CheckInPersistenceServiceIT.java | 17 +- .../CompletedPersistenceServiceIT.java | 31 +- .../KeyResultPersistenceServiceIT.java | 81 ++-- .../ObjectivePersistenceServiceIT.java | 101 ++-- .../OverviewPersistenceServiceIT.java | 74 +-- .../persistence/PersistenceBaseTestIT.java | 34 +- .../QuarterPersistenceServiceIT.java | 31 +- .../persistence/TeamPersistenceServiceIT.java | 9 +- .../persistence/UserPersistenceServiceIT.java | 38 +- .../UserTeamPersistenceServiceIT.java | 3 +- .../ActionValidationServiceTest.java | 249 ++++++---- .../AlignmentValidationServiceTest.java | 19 +- .../CheckInValidationServiceTest.java | 223 ++++++--- .../CompletedValidationServiceTest.java | 80 +-- .../KeyResultValidationServiceTest.java | 225 ++++++--- .../ObjectiveValidationServiceTest.java | 447 ++++++++++++----- .../OverviewValidationServiceTest.java | 10 +- .../QuarterValidationServiceTest.java | 39 +- .../validation/TeamValidationServiceTest.java | 55 ++- .../validation/UserValidationServiceTest.java | 256 ++++++---- .../validation/ValidationBaseTest.java | 51 +- .../ch/puzzle/okr/test/AssertionHelper.java | 16 +- .../puzzle/okr/test/CheckInTestHelpers.java | 63 ++- .../puzzle/okr/test/KeyResultTestHelpers.java | 144 ++++-- .../okr/test/SpringIntegrationTest.java | 3 +- .../java/ch/puzzle/okr/test/TestHelper.java | 31 +- .../test/dto/builder/ObjectiveDtoBuilder.java | 14 +- .../quarter/check/QuarterRangeChecker.java | 1 - .../check/QuarterRangeCheckerTest.java | 12 +- .../quarter/generate/QuarterLabelTest.java | 66 +-- .../util/quarter/generate/QuartersTest.java | 231 +++++---- .../generate/h2/QuarterFunctionTest.java | 18 +- frontend/.prettierrc | 8 +- frontend/README.md | 21 +- frontend/cypress.config.ts | 6 +- frontend/cypress/e2e/check-in.cy.ts | 54 ++- .../cypress/e2e/duplicate-objective.cy.ts | 56 ++- frontend/cypress/e2e/key-result.cy.ts | 197 +++++--- frontend/cypress/e2e/login.cy.ts | 35 +- frontend/cypress/e2e/objective-backlog.cy.ts | 115 +++-- frontend/cypress/e2e/objective-crud.cy.ts | 77 ++- frontend/cypress/e2e/objective.cy.ts | 138 ++++-- frontend/cypress/e2e/overview.cy.ts | 35 +- frontend/cypress/e2e/routing.cy.ts | 18 +- frontend/cypress/e2e/scoring.cy.ts | 54 ++- frontend/cypress/e2e/tab.cy.ts | 111 +++-- frontend/cypress/e2e/team.cy.ts | 61 ++- frontend/cypress/e2e/teammanagement.cy.ts | 425 +++++++++++----- frontend/cypress/support/commands.ts | 79 +-- frontend/cypress/support/e2e.ts | 32 +- .../helper/dom-helper/angularSearchBox.ts | 9 +- .../dom-helper/dialogs/checkInDialog.ts | 19 +- .../dialogs/checkInHistoryDialog.ts | 12 +- .../dom-helper/dialogs/confirmDialog.ts | 14 +- .../helper/dom-helper/dialogs/dialog.ts | 12 +- .../dom-helper/dialogs/inviteMembersDialog.ts | 20 +- .../dom-helper/dialogs/keyResultDialog.ts | 24 +- .../dom-helper/dialogs/objectiveDialog.ts | 20 +- .../helper/dom-helper/dialogs/teamDialog.ts | 6 +- .../support/helper/dom-helper/filterHelper.ts | 14 +- .../helper/dom-helper/pageObjectMapperBase.ts | 19 +- .../dom-helper/pages/keyResultDetailPage.ts | 27 +- .../helper/dom-helper/pages/overviewPage.ts | 106 ++-- .../support/helper/dom-helper/pages/page.ts | 3 +- .../dom-helper/pages/teammanagementPage.ts | 49 +- .../cypress/support/helper/keyResultHelper.ts | 3 +- .../cypress/support/helper/objectiveHelper.ts | 6 +- .../cypress/support/helper/scoringSupport.ts | 38 +- frontend/cypress/support/helper/utils.ts | 34 +- frontend/eslint.config.mjs | 4 +- frontend/package-lock.json | 316 ++++++------ frontend/src/app/app-routing.module.ts | 44 +- frontend/src/app/app.component.spec.ts | 35 +- frontend/src/app/app.component.ts | 21 +- frontend/src/app/app.module.ts | 48 +- .../action-plan/action-plan.component.html | 6 +- .../action-plan/action-plan.component.spec.ts | 92 +++- .../action-plan/action-plan.component.ts | 45 +- .../application-banner.component.html | 7 +- .../application-banner.component.scss | 2 +- .../application-banner.component.spec.ts | 72 +-- .../application-banner.component.ts | 13 +- .../application-top-bar.component.html | 46 +- .../application-top-bar.component.scss | 2 +- .../application-top-bar.component.spec.ts | 53 +- .../application-top-bar.component.ts | 21 +- .../check-in-history-dialog.component.html | 18 +- .../check-in-history-dialog.component.spec.ts | 33 +- .../check-in-history-dialog.component.ts | 22 +- .../check-in-form-metric.component.spec.ts | 53 +- .../check-in-form-metric.component.ts | 9 +- .../metric-check-in-directive.spec.ts | 24 +- .../metric-check-in-directive.ts | 22 +- .../check-in-form-ordinal.component.html | 30 +- .../check-in-form-ordinal.component.scss | 2 +- .../check-in-form-ordinal.component.spec.ts | 41 +- .../check-in-form-ordinal.component.ts | 5 +- .../check-in-form.component.html | 22 +- .../check-in-form.component.spec.ts | 134 ++--- .../check-in-form/check-in-form.component.ts | 40 +- .../confidence/confidence.component.html | 12 +- .../confidence/confidence.component.spec.ts | 31 +- .../confidence/confidence.component.ts | 14 +- .../key-result-form.component.spec.ts | 123 +++-- .../key-result-form.component.ts | 73 +-- .../keyresult-detail.component.html | 28 +- .../keyresult-detail.component.scss | 4 +- .../keyresult-detail.component.spec.ts | 86 ++-- .../keyresult-detail.component.ts | 52 +- .../keyresult-dialog.component.html | 14 +- .../keyresult-dialog.component.spec.ts | 451 +++++++++-------- .../keyresult-dialog.component.ts | 40 +- .../keyresult-type.component.scss | 2 +- .../keyresult-type.component.spec.ts | 217 +++++---- .../keyresult-type.component.ts | 43 +- .../keyresult/keyresult.component.html | 6 +- .../keyresult/keyresult.component.scss | 2 +- .../keyresult/keyresult.component.spec.ts | 14 +- .../keyresult/keyresult.component.ts | 6 +- .../objective-detail.component.html | 17 +- .../objective-detail.component.scss | 2 +- .../objective-detail.component.spec.ts | 52 +- .../objective-detail.component.ts | 19 +- .../objective-filter.component.html | 6 +- .../objective-filter.component.spec.ts | 74 +-- .../objective-filter.component.ts | 29 +- .../objective/ObjectiveMenuActions.ts | 56 ++- .../objective/ObjectiveMenuAfterActions.ts | 80 +-- .../objective/objective.component.html | 12 +- .../objective/objective.component.scss | 2 +- .../objective/objective.component.spec.ts | 78 +-- .../objective/objective.component.ts | 19 +- .../overview/overview.component.html | 18 +- .../overview/overview.component.spec.ts | 122 +++-- .../components/overview/overview.component.ts | 41 +- .../quarter-filter.component.spec.ts | 96 ++-- .../quarter-filter.component.ts | 49 +- .../team-filter/team-filter.component.spec.ts | 284 +++++++---- .../team-filter/team-filter.component.ts | 57 ++- .../app/components/team/team.component.html | 5 +- .../components/team/team.component.spec.ts | 89 ++-- .../src/app/components/team/team.component.ts | 43 +- frontend/src/app/guards/auth.guard.spec.ts | 80 +-- frontend/src/app/guards/auth.guard.ts | 29 +- .../interceptors/error-interceptor.service.ts | 54 +-- .../interceptors/error.interceptor.spec.ts | 341 +++++++++---- .../interceptors/oauth.interceptor.spec.ts | 21 +- .../src/app/interceptors/oauth.interceptor.ts | 35 +- .../src/app/services/action.service.spec.ts | 5 +- frontend/src/app/services/action.service.ts | 2 +- .../src/app/services/check-in.service.spec.ts | 22 +- frontend/src/app/services/check-in.service.ts | 2 +- frontend/src/app/services/completed.servce.ts | 2 +- .../app/services/completed.service.spec.ts | 5 +- .../src/app/services/config.service.spec.ts | 5 +- frontend/src/app/services/config.service.ts | 5 +- .../services/customization.service.spec.ts | 129 +++-- .../src/app/services/customization.service.ts | 26 +- .../src/app/services/dialog.service.spec.ts | 185 ++++--- frontend/src/app/services/dialog.service.ts | 23 +- .../app/services/keyresult.service.spec.ts | 3 +- .../src/app/services/keyresult.service.ts | 9 +- .../objective-menu-actions.service.spec.ts | 56 ++- .../objective-menu-actions.service.ts | 18 +- .../app/services/objective.service.spec.ts | 5 +- .../src/app/services/objective.service.ts | 9 +- .../src/app/services/overview.service.spec.ts | 26 +- frontend/src/app/services/overview.service.ts | 11 +- .../src/app/services/quarter.service.spec.ts | 5 +- frontend/src/app/services/quarter.service.ts | 10 +- .../app/services/refresh-data.service.spec.ts | 3 +- .../src/app/services/refresh-data.service.ts | 8 +- .../src/app/services/team.service.spec.ts | 5 +- frontend/src/app/services/team.service.ts | 34 +- .../src/app/services/toaster.service.spec.ts | 33 +- frontend/src/app/services/toaster.service.ts | 2 +- .../src/app/services/user.service.spec.ts | 51 +- frontend/src/app/services/user.service.ts | 30 +- frontend/src/app/shared/common.spec.ts | 459 ++++++++++++------ frontend/src/app/shared/common.ts | 48 +- frontend/src/app/shared/constantLibary.ts | 78 ++- .../dialog-template-core.component.html | 6 +- .../dialog-template-core.component.scss | 2 +- .../dialog-template-core.component.ts | 5 +- .../okr-tangram/okr-tangram.component.html | 8 +- .../okr-tangram/okr-tangram.component.ts | 7 +- .../puzzle-icon-button.component.html | 13 +- .../puzzle-icon-button.component.ts | 7 +- .../puzzle-icon/puzzle-icon.component.html | 7 +- .../puzzle-icon/puzzle-icon.component.ts | 4 +- .../custom/scoring/scoring.component.html | 23 +- .../custom/scoring/scoring.component.scss | 4 +- .../custom/scoring/scoring.component.spec.ts | 157 +++--- .../custom/scoring/scoring.component.ts | 46 +- .../custom/spinner/spinner.component.html | 6 +- .../custom/spinner/spinner.component.ts | 2 +- frontend/src/app/shared/customRouter.ts | 3 +- .../complete-dialog.component.html | 7 +- .../complete-dialog.component.spec.ts | 105 ++-- .../complete-dialog.component.ts | 19 +- .../confirm-dialog.component.spec.ts | 35 +- .../confirm-dialog.component.ts | 16 +- .../example-dialog.component.html | 6 +- .../example-dialog.component.spec.ts | 193 ++++---- .../example-dialog.component.ts | 26 +- .../objective-form.component.html | 15 +- .../objective-form.component.spec.ts | 377 ++++++++------ .../objective-form.component.ts | 117 +++-- .../unit-transformation.pipe.spec.ts | 30 +- .../unit-transformation.pipe.ts | 5 +- frontend/src/app/shared/routeUtils.spec.ts | 15 +- frontend/src/app/shared/shared.module.ts | 8 +- .../shared/sidepanel/sidepanel.component.scss | 2 +- .../shared/sidepanel/sidepanel.component.ts | 31 +- frontend/src/app/shared/testData.ts | 200 ++++---- .../src/app/shared/types/enums/ButtonState.ts | 2 +- .../src/app/shared/types/enums/CloseState.ts | 2 +- .../src/app/shared/types/enums/HttpType.ts | 2 +- frontend/src/app/shared/types/enums/State.ts | 2 +- .../src/app/shared/types/enums/ToasterType.ts | 2 +- frontend/src/app/shared/types/enums/Unit.ts | 2 +- .../src/app/shared/types/enums/UserRole.ts | 2 +- frontend/src/app/shared/types/enums/Zone.ts | 2 +- .../app/shared/types/model/ClientConfig.ts | 4 +- .../src/app/shared/types/model/Quarter.ts | 7 +- .../app/shared/types/model/UserTableEntry.ts | 2 +- frontend/src/app/shared/validators.ts | 17 +- .../add-edit-team-dialog.component.html | 7 +- .../add-edit-team-dialog.component.scss | 2 +- .../add-edit-team-dialog.component.spec.ts | 62 ++- .../add-edit-team-dialog.component.ts | 50 +- .../add-member-to-team-dialog.component.html | 13 +- ...dd-member-to-team-dialog.component.spec.ts | 88 ++-- .../add-member-to-team-dialog.component.ts | 55 ++- .../add-user-team.component.html | 16 +- .../add-user-team.component.spec.ts | 73 ++- .../add-user-team/add-user-team.component.ts | 39 +- .../delete-user/delete-user.component.html | 6 +- .../delete-user/delete-user.component.spec.ts | 161 +++--- .../delete-user/delete-user.component.ts | 76 ++- .../edit-okr-champion.component.html | 46 +- .../edit-okr-champion.component.scss | 2 +- .../edit-okr-champion.component.ts | 11 +- .../invite-user-dialog.component.html | 45 +- .../invite-user-dialog.component.spec.ts | 75 ++- .../invite-user-dialog.component.ts | 18 +- .../member-detail.component.html | 35 +- .../member-detail.component.spec.ts | 95 ++-- .../member-detail/member-detail.component.ts | 66 +-- .../member-list-mobile.component.html | 30 +- .../member-list-mobile.component.scss | 2 +- .../member-list-mobile.component.spec.ts | 22 +- .../member-list-mobile.component.ts | 3 +- .../member-list-table.component.html | 12 +- .../member-list-table.component.scss | 2 +- .../member-list-table.component.spec.ts | 104 ++-- .../member-list-table.component.ts | 61 ++- .../member-list/member-list.component.html | 18 +- .../member-list/member-list.component.scss | 2 +- .../member-list/member-list.component.spec.ts | 225 +++++---- .../member-list/member-list.component.ts | 39 +- .../new-user/new-user.component.html | 18 +- .../new-user/new-user.component.spec.ts | 23 +- .../new-user/new-user.component.ts | 7 +- .../new-user/unique-mail.directive.spec.ts | 17 +- .../new-user/unique-mail.validator.ts | 4 +- .../team-management/okr-champion.pipe.spec.ts | 11 +- .../app/team-management/okr-champion.pipe.ts | 2 +- .../src/app/team-management/roles.pipe.ts | 5 +- .../search-team-management.component.html | 12 +- .../search-team-management.component.spec.ts | 150 +++--- .../search-team-management.component.ts | 58 ++- .../show-edit-role.component.html | 5 +- .../show-edit-role.component.spec.ts | 18 +- .../show-edit-role.component.ts | 14 +- .../team-list/team-list.component.html | 4 +- .../team-list/team-list.component.scss | 2 +- .../team-list/team-list.component.spec.ts | 31 +- .../team-list/team-list.component.ts | 19 +- .../team-management-banner.component.html | 13 +- .../team-management-banner.component.scss | 2 +- .../team-management-banner.component.spec.ts | 30 +- .../team-management-banner.component.ts | 9 +- ...am-management-mobile-filter.component.html | 6 +- ...management-mobile-filter.component.spec.ts | 60 ++- ...team-management-mobile-filter.component.ts | 15 +- .../team-management-routing.module.ts | 44 +- .../team-management.component.spec.ts | 29 +- .../team-management.component.ts | 2 +- .../team-management/team-management.module.ts | 6 +- .../team-role-dropdown.component.html | 4 +- .../team-role-dropdown.component.spec.ts | 33 +- .../team-role-dropdown.component.ts | 2 +- .../app/team-management/teams.pipe.spec.ts | 22 +- .../src/app/team-management/teams.pipe.ts | 9 +- frontend/src/environments/environment.prod.ts | 4 +- frontend/src/environments/environment.ts | 12 +- frontend/src/global.ts | 7 +- frontend/src/index.html | 13 +- .../src/style/custom_angular.components.scss | 4 +- frontend/src/style/custom_angular.scss | 6 +- frontend/src/style/custom_bootstrap.scss | 14 +- frontend/src/style/styles.scss | 78 +-- 539 files changed, 12965 insertions(+), 8044 deletions(-) diff --git a/backend/src/main/java/ch/puzzle/okr/Constants.java b/backend/src/main/java/ch/puzzle/okr/Constants.java index c7cf839961..63989d249c 100644 --- a/backend/src/main/java/ch/puzzle/okr/Constants.java +++ b/backend/src/main/java/ch/puzzle/okr/Constants.java @@ -1,12 +1,11 @@ package ch.puzzle.okr; +import static java.util.Map.entry; + import ch.puzzle.okr.dto.checkin.*; import ch.puzzle.okr.dto.keyresult.*; - import java.util.Map; -import static java.util.Map.entry; - public class Constants { private Constants() { } @@ -29,11 +28,11 @@ private Constants() { public static final String CHECK_IN_KEY_RESULT_ID_ATTRIBUTE_NAME = "keyResultId"; public static final String KEY_RESULT_TYPE_ATTRIBUTE_NAME = "keyResultType"; - public static final Map> KEY_RESULT_MAP = Map.ofEntries( - entry(KEY_RESULT_TYPE_METRIC, KeyResultMetricDto.class), - entry(KEY_RESULT_TYPE_ORDINAL, KeyResultOrdinalDto.class)); + public static final Map> KEY_RESULT_MAP = Map + .ofEntries(entry(KEY_RESULT_TYPE_METRIC, KeyResultMetricDto.class), + entry(KEY_RESULT_TYPE_ORDINAL, KeyResultOrdinalDto.class)); - public static final Map> CHECK_IN_MAP = Map.ofEntries( - entry(KEY_RESULT_TYPE_METRIC, CheckInMetricDto.class), - entry(KEY_RESULT_TYPE_ORDINAL, CheckInOrdinalDto.class)); + public static final Map> CHECK_IN_MAP = Map + .ofEntries(entry(KEY_RESULT_TYPE_METRIC, CheckInMetricDto.class), + entry(KEY_RESULT_TYPE_ORDINAL, CheckInOrdinalDto.class)); } diff --git a/backend/src/main/java/ch/puzzle/okr/ErrorKey.java b/backend/src/main/java/ch/puzzle/okr/ErrorKey.java index f5a67168eb..c460e66b4e 100644 --- a/backend/src/main/java/ch/puzzle/okr/ErrorKey.java +++ b/backend/src/main/java/ch/puzzle/okr/ErrorKey.java @@ -1,8 +1,22 @@ package ch.puzzle.okr; public enum ErrorKey { - ATTRIBUTE_NULL, ATTRIBUTE_CHANGED, ATTRIBUTE_SET_FORBIDDEN, ATTRIBUTE_NOT_SET, ATTRIBUTE_CANNOT_CHANGE, - ATTRIBUTE_MUST_BE_DRAFT, KEY_RESULT_CONVERSION, ALREADY_EXISTS_SAME_NAME, CONVERT_TOKEN, DATA_HAS_BEEN_UPDATED, - MODEL_NULL, MODEL_WITH_ID_NOT_FOUND, NOT_AUTHORIZED_TO_READ, NOT_AUTHORIZED_TO_WRITE, NOT_AUTHORIZED_TO_DELETE, - TOKEN_NULL, TRIED_TO_DELETE_LAST_ADMIN, TRIED_TO_REMOVE_LAST_OKR_CHAMPION + ATTRIBUTE_NULL, + ATTRIBUTE_CHANGED, + ATTRIBUTE_SET_FORBIDDEN, + ATTRIBUTE_NOT_SET, + ATTRIBUTE_CANNOT_CHANGE, + ATTRIBUTE_MUST_BE_DRAFT, + KEY_RESULT_CONVERSION, + ALREADY_EXISTS_SAME_NAME, + CONVERT_TOKEN, + DATA_HAS_BEEN_UPDATED, + MODEL_NULL, + MODEL_WITH_ID_NOT_FOUND, + NOT_AUTHORIZED_TO_READ, + NOT_AUTHORIZED_TO_WRITE, + NOT_AUTHORIZED_TO_DELETE, + TOKEN_NULL, + TRIED_TO_DELETE_LAST_ADMIN, + TRIED_TO_REMOVE_LAST_OKR_CHAMPION } diff --git a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java index 2e517f4d59..40180a1765 100644 --- a/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java +++ b/backend/src/main/java/ch/puzzle/okr/ForwardFilter.java @@ -5,14 +5,11 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; import org.springframework.web.filter.GenericFilterBean; -import java.io.IOException; -import java.util.Arrays; - public class ForwardFilter extends GenericFilterBean { private static final Logger logger = LoggerFactory.getLogger(ForwardFilter.class); diff --git a/backend/src/main/java/ch/puzzle/okr/OkrErrorAttributes.java b/backend/src/main/java/ch/puzzle/okr/OkrErrorAttributes.java index 0a721ff03b..1b84868059 100644 --- a/backend/src/main/java/ch/puzzle/okr/OkrErrorAttributes.java +++ b/backend/src/main/java/ch/puzzle/okr/OkrErrorAttributes.java @@ -1,13 +1,12 @@ package ch.puzzle.okr; import ch.puzzle.okr.exception.OkrResponseStatusException; +import java.util.Map; import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.stereotype.Component; import org.springframework.web.context.request.WebRequest; -import java.util.Map; - @Component public class OkrErrorAttributes extends DefaultErrorAttributes { diff --git a/backend/src/main/java/ch/puzzle/okr/OpenAPI30Configuration.java b/backend/src/main/java/ch/puzzle/okr/OpenAPI30Configuration.java index a7613f5b26..f0e5fe5652 100644 --- a/backend/src/main/java/ch/puzzle/okr/OpenAPI30Configuration.java +++ b/backend/src/main/java/ch/puzzle/okr/OpenAPI30Configuration.java @@ -12,9 +12,15 @@ public class OpenAPI30Configuration { @Bean public OpenAPI customizeOpenAPI() { final String securitySchemeName = "bearerAuth"; - return new OpenAPI().addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) - .components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme() - .name(securitySchemeName).type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"))); + return new OpenAPI() + .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) + .components(new Components() + .addSecuritySchemes(securitySchemeName, + new SecurityScheme() + .name(securitySchemeName) + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT"))); } } diff --git a/backend/src/main/java/ch/puzzle/okr/SecurityConfig.java b/backend/src/main/java/ch/puzzle/okr/SecurityConfig.java index b4b8a07e6f..29706319e3 100644 --- a/backend/src/main/java/ch/puzzle/okr/SecurityConfig.java +++ b/backend/src/main/java/ch/puzzle/okr/SecurityConfig.java @@ -1,5 +1,9 @@ package ch.puzzle.okr; +import static org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP; +import static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER; +import static org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK; + import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jwt.proc.ConfigurableJWTProcessor; import com.nimbusds.jwt.proc.DefaultJWTProcessor; @@ -33,10 +37,6 @@ import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter; import org.springframework.security.web.header.writers.StaticHeadersWriter; -import static org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP; -import static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER; -import static org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK; - @Configuration @EnableWebSecurity @EnableMethodSecurity @@ -58,10 +58,12 @@ public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http, @Value("${c http.addFilterAfter(new ForwardFilter(), BasicAuthenticationFilter.class); logger.debug("*** apiSecurityFilterChain reached"); setHeaders(http); - return http.cors(Customizer.withDefaults()) + return http + .cors(Customizer.withDefaults()) .authorizeHttpRequests(e -> e.requestMatchers("/api/**").authenticated().anyRequest().permitAll()) .exceptionHandling(e -> e.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))) - .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())).build(); + .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())) + .build(); } @Bean @@ -75,14 +77,15 @@ JWTProcessor jwtProcessor(JWTClaimsSetAwareJWSKeySelector jwtProcessor, OAuth2TokenValidator jwtValidator) { NimbusJwtDecoder decoder = new NimbusJwtDecoder(jwtProcessor); OAuth2TokenValidator validator = new DelegatingOAuth2TokenValidator<>(JwtValidators.createDefault(), - jwtValidator); + jwtValidator); decoder.setJwtValidator(validator); return decoder; } private HttpSecurity setHeaders(HttpSecurity http) throws Exception { return http - .headers(headers -> headers.contentSecurityPolicy(c -> c.policyDirectives(okrContentSecurityPolicy())) + .headers(headers -> headers + .contentSecurityPolicy(c -> c.policyDirectives(okrContentSecurityPolicy())) .crossOriginEmbedderPolicy(c -> c.policy(REQUIRE_CORP)) .crossOriginOpenerPolicy(c -> c.policy(OPENER_SAME_ORIGIN)) .crossOriginResourcePolicy(c -> c.policy(RESOURCE_SAME_ORIGIN)) @@ -96,32 +99,31 @@ private HttpSecurity setHeaders(HttpSecurity http) throws Exception { private String okrContentSecurityPolicy() { return "default-src 'self';" // - + "script-src 'self' 'unsafe-inline';" // - + " style-src 'self' 'unsafe-inline';" // - + " object-src 'none';" // - + " base-uri 'self';" // - + " connect-src 'self' " + connectSrc + ";" // - + " font-src 'self';" // - + " frame-src 'self';" // - + " img-src 'self' data: ;" // - + " manifest-src 'self';" // - + " media-src 'self';" // - + " worker-src 'none';"; // + + "script-src 'self' 'unsafe-inline';" // + + " style-src 'self' 'unsafe-inline';" // + + " object-src 'none';" // + + " base-uri 'self';" // + + " connect-src 'self' " + connectSrc + ";" // + + " font-src 'self';" // + + " frame-src 'self';" // + + " img-src 'self' data: ;" // + + " manifest-src 'self';" // + + " media-src 'self';" // + + " worker-src 'none';"; // } private String okrPermissionPolicy() { return "accelerometer=(), ambient-light-sensor=(), autoplay=(), " - + "battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), " - + "execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=()," - + " geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), " - + "midi=(), navigation-override=(), payment=(), picture-in-picture=()," - + " publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), " - + "usb=(), web-share=(), xr-spatial-tracking=()"; + + "battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), " + + "execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=()," + + " geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), " + + "midi=(), navigation-override=(), payment=(), picture-in-picture=()," + + " publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), " + + "usb=(), web-share=(), xr-spatial-tracking=()"; } @Bean - public AuthenticationEventPublisher authenticationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { return new DefaultAuthenticationEventPublisher(applicationEventPublisher); } diff --git a/backend/src/main/java/ch/puzzle/okr/UserKeyGenerator.java b/backend/src/main/java/ch/puzzle/okr/UserKeyGenerator.java index 144a056e30..c66adf8a65 100644 --- a/backend/src/main/java/ch/puzzle/okr/UserKeyGenerator.java +++ b/backend/src/main/java/ch/puzzle/okr/UserKeyGenerator.java @@ -2,10 +2,9 @@ import ch.puzzle.okr.models.User; import ch.puzzle.okr.multitenancy.TenantContext; -import org.springframework.cache.interceptor.KeyGenerator; - import java.lang.reflect.Method; import java.text.MessageFormat; +import org.springframework.cache.interceptor.KeyGenerator; public class UserKeyGenerator implements KeyGenerator { @Override diff --git a/backend/src/main/java/ch/puzzle/okr/controller/ActionController.java b/backend/src/main/java/ch/puzzle/okr/controller/ActionController.java index d6b9855b7b..7252d122bb 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/ActionController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/ActionController.java @@ -9,9 +9,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.web.bind.annotation.*; - import java.util.List; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("api/v2/action") @@ -30,8 +29,8 @@ public ActionController(ActionAuthorizationService actionAuthorizationService, A @Content(mediaType = "application/json", schema = @Schema(implementation = ActionDto.class)) }), @ApiResponse(responseCode = "400", description = "Can't update Actions, attributes are not set", content = @Content) }) @PutMapping - public void updateActions( - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Action as json to update existing Actions.", required = true) @RequestBody List actionDtoList) { + public void updateActions(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Action as json to update existing Actions.", required = true) + @RequestBody List actionDtoList) { List actionList = actionMapper.toActions(actionDtoList); actionAuthorizationService.updateEntities(actionList); } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/AlignmentController.java b/backend/src/main/java/ch/puzzle/okr/controller/AlignmentController.java index 85b6a77ec1..f63a090ea3 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/AlignmentController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/AlignmentController.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -15,8 +16,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @RestController @RequestMapping("api/v2/alignments") public class AlignmentController { @@ -24,7 +23,7 @@ public class AlignmentController { private final AlignmentSelectionBusinessService alignmentSelectionBusinessService; public AlignmentController(AlignmentSelectionMapper alignmentSelectionMapper, - AlignmentSelectionBusinessService alignmentSelectionBusinessService) { + AlignmentSelectionBusinessService alignmentSelectionBusinessService) { this.alignmentSelectionMapper = alignmentSelectionMapper; this.alignmentSelectionBusinessService = alignmentSelectionBusinessService; } @@ -35,11 +34,12 @@ public AlignmentController(AlignmentSelectionMapper alignmentSelectionMapper, @Content(mediaType = "application/json", schema = @Schema(implementation = AlignmentObjectiveDto.class)) }), @ApiResponse(responseCode = "400", description = "Can't return list of objectives with their key results to select the alignment", content = @Content) }) @GetMapping("/selections") - public ResponseEntity> getAlignmentSelections( - @RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter, - @RequestParam(required = false, defaultValue = "", name = "team") Long teamFilter) { - return ResponseEntity.status(HttpStatus.OK) - .body(alignmentSelectionMapper.toDto(alignmentSelectionBusinessService - .getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterFilter, teamFilter))); + public ResponseEntity> getAlignmentSelections(@RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter, + @RequestParam(required = false, defaultValue = "", name = "team") Long teamFilter) { + return ResponseEntity + .status(HttpStatus.OK) + .body(alignmentSelectionMapper + .toDto(alignmentSelectionBusinessService + .getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterFilter, teamFilter))); } } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/CheckInController.java b/backend/src/main/java/ch/puzzle/okr/controller/CheckInController.java index 83c6030f2e..976e0ceb24 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/CheckInController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/CheckInController.java @@ -34,7 +34,8 @@ public CheckInController(CheckInMapper checkInMapper, CheckInAuthorizationServic @ApiResponse(responseCode = "404", description = "Did not find a Check-in with a specified ID", content = @Content) }) @GetMapping("/{id}") public ResponseEntity getCheckInById(@PathVariable long id) { - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity + .status(HttpStatus.OK) .body(checkInMapper.toDto(this.checkInAuthorizationService.getEntityById(id))); } @@ -47,9 +48,8 @@ public ResponseEntity getCheckInById(@PathVariable long id) { @ApiResponse(responseCode = "404", description = "Given ID of Check-in wasn't found.", content = @Content), @ApiResponse(responseCode = "422", description = "Can't update Check-in since Check-in was updated or deleted by another user.", content = @Content) }) @PutMapping("/{id}") - public ResponseEntity updateCheckIn( - @Parameter(description = "The ID for updating a Check-in.", required = true) @PathVariable Long id, - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to update an existing Check-in.", required = true) @RequestBody CheckInDto checkInDto) { + public ResponseEntity updateCheckIn(@Parameter(description = "The ID for updating a Check-in.", required = true) + @PathVariable Long id, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to update an existing Check-in.", required = true) @RequestBody CheckInDto checkInDto) { CheckIn checkIn = checkInMapper.toCheckIn(checkInDto); CheckInDto updatedCheckIn = this.checkInMapper .toDto(this.checkInAuthorizationService.updateEntity(id, checkIn)); @@ -63,8 +63,8 @@ public ResponseEntity updateCheckIn( @ApiResponse(responseCode = "400", description = "Can't create new Check-in, not allowed to give an ID", content = @Content), @ApiResponse(responseCode = "401", description = "Not authorized to create Check-in", content = @Content) }) @PostMapping - public ResponseEntity createCheckIn( - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to create a new Check-in.", required = true) @RequestBody CheckInDto checkInDto) { + public ResponseEntity createCheckIn(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to create a new Check-in.", required = true) + @RequestBody CheckInDto checkInDto) { CheckIn checkIn = checkInMapper.toCheckIn(checkInDto); CheckInDto createdCheckIn = checkInMapper.toDto(checkInAuthorizationService.createEntity(checkIn)); return ResponseEntity.status(HttpStatus.CREATED).body(createdCheckIn); @@ -75,8 +75,8 @@ public ResponseEntity createCheckIn( @ApiResponse(responseCode = "401", description = "Not authorized to delete Check-in", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Check-in with requested ID") }) @DeleteMapping("/{id}") - public void deleteCheckInById( - @Parameter(description = "The ID of an Check-in to delete it.", required = true) @PathVariable long id) { + public void deleteCheckInById(@Parameter(description = "The ID of an Check-in to delete it.", required = true) + @PathVariable long id) { this.checkInAuthorizationService.deleteEntityById(id); } } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/ClientConfigController.java b/backend/src/main/java/ch/puzzle/okr/controller/ClientConfigController.java index ec45e2f782..1fd85d9089 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/ClientConfigController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/ClientConfigController.java @@ -20,7 +20,8 @@ public ClientConfigController(ClientConfigService configService) { @GetMapping("/config") public ResponseEntity getConfig(HttpServletRequest request) { - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity + .status(HttpStatus.OK) .body(configService.getConfigBasedOnActiveEnv(request.getServerName())); } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/CompletedController.java b/backend/src/main/java/ch/puzzle/okr/controller/CompletedController.java index 4b8e10e5dc..b7cbfcaeb9 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/CompletedController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/CompletedController.java @@ -21,7 +21,7 @@ public class CompletedController { private final CompletedMapper completedMapper; public CompletedController(CompletedAuthorizationService completedAuthorizationService, - CompletedMapper completedMapper) { + CompletedMapper completedMapper) { this.completedAuthorizationService = completedAuthorizationService; this.completedMapper = completedMapper; } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/KeyResultController.java b/backend/src/main/java/ch/puzzle/okr/controller/KeyResultController.java index 0940bdc333..a52c61761e 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/KeyResultController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/KeyResultController.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.controller; +import static org.springframework.http.HttpStatus.*; + import ch.puzzle.okr.dto.checkin.CheckInDto; import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.dto.keyresult.KeyResultMetricDto; @@ -18,13 +20,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - -import static org.springframework.http.HttpStatus.*; - @RestController @RequestMapping("api/v2/keyresults") public class KeyResultController { @@ -36,8 +35,8 @@ public class KeyResultController { private final ActionMapper actionMapper; public KeyResultController(KeyResultAuthorizationService keyResultAuthorizationService, - ActionAuthorizationService actionAuthorizationService, KeyResultMapper keyResultMapper, - CheckInMapper checkInMapper, ActionMapper actionMapper) { + ActionAuthorizationService actionAuthorizationService, KeyResultMapper keyResultMapper, + CheckInMapper checkInMapper, ActionMapper actionMapper) { this.keyResultAuthorizationService = keyResultAuthorizationService; this.actionAuthorizationService = actionAuthorizationService; this.keyResultMapper = keyResultMapper; @@ -66,8 +65,8 @@ public KeyResultDto getKeyResultById(@PathVariable long id) { @ApiResponse(responseCode = "401", description = "Not authorized to read Check-ins from a KeyResult", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find a KeyResult with a specified ID to get Check-ins from.", content = @Content) }) @GetMapping("/{id}/checkins") - public List getCheckInsFromKeyResult( - @Parameter(description = "The ID for getting all Check-ins from a KeyResult.", required = true) @PathVariable long id) { + public List getCheckInsFromKeyResult(@Parameter(description = "The ID for getting all Check-ins from a KeyResult.", required = true) + @PathVariable long id) { return keyResultAuthorizationService.getAllCheckInsByKeyResult(id).stream().map(checkInMapper::toDto).toList(); } @@ -98,15 +97,15 @@ public ResponseEntity createKeyResult(@RequestBody KeyResultDto ke @ApiResponse(responseCode = "404", description = "Did not find a KeyResult with a specified ID to update.", content = @Content), @ApiResponse(responseCode = "422", description = "Can't update KeyResult since KeyResult was updated or deleted by another user.", content = @Content) }) @PutMapping("/{id}") - public ResponseEntity updateKeyResult( - @Parameter(description = "The ID for updating a KeyResult.", required = true) @PathVariable long id, - @RequestBody KeyResultDto keyResultDto) { + public ResponseEntity updateKeyResult(@Parameter(description = "The ID for updating a KeyResult.", required = true) + @PathVariable long id, @RequestBody KeyResultDto keyResultDto) { KeyResult keyResult = keyResultMapper.toKeyResult(keyResultDto); List actionList = actionMapper.toActions(keyResultDto.getActionList(), keyResult); boolean isKeyResultImUsed = keyResultAuthorizationService.isImUsed(id, keyResult); - KeyResultWithActionList updatedKeyResult = keyResultAuthorizationService.updateEntities(id, keyResult, - actionList); - return ResponseEntity.status(isKeyResultImUsed ? IM_USED : OK) + KeyResultWithActionList updatedKeyResult = keyResultAuthorizationService + .updateEntities(id, keyResult, actionList); + return ResponseEntity + .status(isKeyResultImUsed ? IM_USED : OK) .body(keyResultMapper.toDto(updatedKeyResult.keyResult(), updatedKeyResult.actionList())); } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/ObjectiveController.java b/backend/src/main/java/ch/puzzle/okr/controller/ObjectiveController.java index 7ca8ae39d8..411c11787a 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/ObjectiveController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/ObjectiveController.java @@ -1,9 +1,12 @@ package ch.puzzle.okr.controller; -import ch.puzzle.okr.dto.checkin.CheckInDto; -import ch.puzzle.okr.dto.keyresult.KeyResultDto; +import static org.springframework.http.HttpStatus.IM_USED; +import static org.springframework.http.HttpStatus.OK; + import ch.puzzle.okr.dto.DuplicateObjectiveDto; import ch.puzzle.okr.dto.ObjectiveDto; +import ch.puzzle.okr.dto.checkin.CheckInDto; +import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.mapper.ObjectiveMapper; import ch.puzzle.okr.mapper.keyresult.KeyResultMapper; import ch.puzzle.okr.models.Action; @@ -17,15 +20,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - -import static org.springframework.http.HttpStatus.IM_USED; -import static org.springframework.http.HttpStatus.OK; - @RestController @RequestMapping("api/v2/objectives") public class ObjectiveController { @@ -35,8 +34,8 @@ public class ObjectiveController { private final ActionAuthorizationService actionAuthorizationService; public ObjectiveController(ObjectiveAuthorizationService objectiveAuthorizationService, - ObjectiveMapper objectiveMapper, KeyResultMapper keyResultMapper, - ActionAuthorizationService actionAuthorizationService) { + ObjectiveMapper objectiveMapper, KeyResultMapper keyResultMapper, + ActionAuthorizationService actionAuthorizationService) { this.objectiveAuthorizationService = objectiveAuthorizationService; this.objectiveMapper = objectiveMapper; this.keyResultMapper = keyResultMapper; @@ -50,9 +49,10 @@ public ObjectiveController(ObjectiveAuthorizationService objectiveAuthorizationS @ApiResponse(responseCode = "401", description = "Not authorized to read an Objective", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find an Objective with a specified ID", content = @Content) }) @GetMapping("/{id}") - public ResponseEntity getObjective( - @Parameter(description = "The ID for getting an Objective.", required = true) @PathVariable Long id) { - return ResponseEntity.status(HttpStatus.OK) + public ResponseEntity getObjective(@Parameter(description = "The ID for getting an Objective.", required = true) + @PathVariable Long id) { + return ResponseEntity + .status(HttpStatus.OK) .body(objectiveMapper.toDto(objectiveAuthorizationService.getEntityById(id))); } @@ -63,9 +63,10 @@ public ResponseEntity getObjective( @ApiResponse(responseCode = "401", description = "Not authorized to read KeyResults from an Objective", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find an Objective with the specified ID to get KeyResults from.", content = @Content) }) @GetMapping("/{id}/keyResults") - public ResponseEntity> getKeyResultsFromObjective( - @Parameter(description = "The ID for getting all KeyResults of an Objective", required = true) @PathVariable long id) { - return ResponseEntity.status(OK) + public ResponseEntity> getKeyResultsFromObjective(@Parameter(description = "The ID for getting all KeyResults of an Objective", required = true) + @PathVariable long id) { + return ResponseEntity + .status(OK) .body(objectiveAuthorizationService.getAllKeyResultsByObjective(id).stream().map(keyResult -> { List actionList = actionAuthorizationService.getActionsByKeyResult(keyResult); return keyResultMapper.toDto(keyResult, actionList); @@ -77,8 +78,8 @@ public ResponseEntity> getKeyResultsFromObjective( @ApiResponse(responseCode = "401", description = "Not authorized to delete an Objective", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Objective with requested ID") }) @DeleteMapping("/{id}") - public void deleteObjectiveById( - @Parameter(description = "The ID of an Objective to delete it.", required = true) @PathVariable long id) { + public void deleteObjectiveById(@Parameter(description = "The ID of an Objective to delete it.", required = true) + @PathVariable long id) { objectiveAuthorizationService.deleteEntityById(id); } @@ -89,8 +90,8 @@ public void deleteObjectiveById( @ApiResponse(responseCode = "400", description = "Can't create new Objective, not allowed to give an ID", content = @Content), @ApiResponse(responseCode = "401", description = "Not authorized to create an Objective", content = @Content) }) @PostMapping - public ResponseEntity createObjective( - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Objective as json to create a new Objective.", required = true) @RequestBody ObjectiveDto objectiveDTO) { + public ResponseEntity createObjective(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Objective as json to create a new Objective.", required = true) + @RequestBody ObjectiveDto objectiveDTO) { Objective objective = objectiveMapper.toObjective(objectiveDTO); ObjectiveDto createdObjective = objectiveMapper.toDto(objectiveAuthorizationService.createEntity(objective)); return ResponseEntity.status(HttpStatus.CREATED).body(createdObjective); @@ -100,11 +101,13 @@ public ResponseEntity createObjective( @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Duplicated a given Objective", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ObjectiveDto.class)) }) }) @PostMapping("/{id}") - public ResponseEntity duplicateObjective( - @Parameter(description = "The ID for duplicating an Objective.", required = true) @PathVariable Long id, - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Objective which should be duplicated as JSON", required = true) @RequestBody DuplicateObjectiveDto duplicateObjectiveDto) { + public ResponseEntity duplicateObjective(@Parameter(description = "The ID for duplicating an Objective.", required = true) + @PathVariable Long id, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Objective which should be duplicated as JSON", required = true) @RequestBody DuplicateObjectiveDto duplicateObjectiveDto) { Objective objective = objectiveMapper.toObjective(duplicateObjectiveDto.objective()); - List keyResults = duplicateObjectiveDto.keyResults().stream().map(keyResultMapper::toKeyResult) + List keyResults = duplicateObjectiveDto + .keyResults() + .stream() + .map(keyResultMapper::toKeyResult) .toList(); ObjectiveDto duplicatedObjectiveDto = objectiveMapper .toDto(objectiveAuthorizationService.duplicateEntity(id, objective, keyResults)); @@ -122,9 +125,8 @@ public ResponseEntity duplicateObjective( @ApiResponse(responseCode = "404", description = "Given ID of Objective wasn't found", content = @Content), @ApiResponse(responseCode = "422", description = "Can't update Objective since Objective was updated or deleted by another user.", content = @Content) }) @PutMapping("/{id}") - public ResponseEntity updateObjective( - @Parameter(description = "The ID for updating an Objective.", required = true) @PathVariable Long id, - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The objective as json to update an existing Objective.", required = true) @RequestBody ObjectiveDto objectiveDTO) { + public ResponseEntity updateObjective(@Parameter(description = "The ID for updating an Objective.", required = true) + @PathVariable Long id, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The objective as json to update an existing Objective.", required = true) @RequestBody ObjectiveDto objectiveDTO) { Objective objective = objectiveMapper.toObjective(objectiveDTO); boolean isObjectiveImUsed = objectiveAuthorizationService.isImUsed(objective); ObjectiveDto updatedObjective = objectiveMapper diff --git a/backend/src/main/java/ch/puzzle/okr/controller/OverviewController.java b/backend/src/main/java/ch/puzzle/okr/controller/OverviewController.java index ff8dfe009d..3ea4163af9 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/OverviewController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/OverviewController.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -15,8 +16,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @RestController @RequestMapping("api/v2/overview") public class OverviewController { @@ -24,7 +23,7 @@ public class OverviewController { private final OverviewAuthorizationService overviewAuthorizationService; public OverviewController(OverviewMapper overviewMapper, - OverviewAuthorizationService overviewAuthorizationService) { + OverviewAuthorizationService overviewAuthorizationService) { this.overviewMapper = overviewMapper; this.overviewAuthorizationService = overviewAuthorizationService; } @@ -37,11 +36,13 @@ public OverviewController(OverviewMapper overviewMapper, @ApiResponse(responseCode = "401", description = "Not authorized to read teams with their objectives", content = @Content), @ApiResponse(responseCode = "404", description = "The quarter or one of the teams were not found", content = @Content) }) @GetMapping("") - public ResponseEntity> getOverview( - @RequestParam(required = false, defaultValue = "", name = "team") List teamFilter, - @RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter, - @RequestParam(required = false, defaultValue = "", name = "objectiveQuery") String objectiveQuery) { - return ResponseEntity.status(HttpStatus.OK).body(overviewMapper - .toDto(overviewAuthorizationService.getFilteredOverview(quarterFilter, teamFilter, objectiveQuery))); + public ResponseEntity> getOverview(@RequestParam(required = false, defaultValue = "", name = "team") List teamFilter, + @RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter, + @RequestParam(required = false, defaultValue = "", name = "objectiveQuery") String objectiveQuery) { + return ResponseEntity + .status(HttpStatus.OK) + .body(overviewMapper + .toDto(overviewAuthorizationService + .getFilteredOverview(quarterFilter, teamFilter, objectiveQuery))); } } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/QuarterController.java b/backend/src/main/java/ch/puzzle/okr/controller/QuarterController.java index 1cc1383dbc..a3c16c47e7 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/QuarterController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/QuarterController.java @@ -1,6 +1,5 @@ package ch.puzzle.okr.controller; -import ch.puzzle.okr.dto.TeamDto; import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.service.business.QuarterBusinessService; import io.swagger.v3.oas.annotations.Operation; @@ -8,14 +7,13 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @RestController @RequestMapping("api/v2/quarters") public class QuarterController { diff --git a/backend/src/main/java/ch/puzzle/okr/controller/TeamController.java b/backend/src/main/java/ch/puzzle/okr/controller/TeamController.java index ccaad22741..51cb9daeed 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/TeamController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/TeamController.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.controller; +import static org.springframework.http.HttpStatus.OK; + import ch.puzzle.okr.dto.TeamDto; import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.mapper.TeamMapper; @@ -11,14 +13,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - -import static org.springframework.http.HttpStatus.OK; - @RestController @RequestMapping("api/v2/teams") public class TeamController { @@ -45,8 +44,8 @@ public List getAllTeams() { @ApiResponse(responseCode = "400", description = "Can't create new Team, not allowed to give an ID", content = @Content), @ApiResponse(responseCode = "401", description = "Not authorized to create a Team", content = @Content) }) @PostMapping - public ResponseEntity createTeam( - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Team as json to create a new Team.", required = true) @RequestBody TeamDto teamDto) { + public ResponseEntity createTeam(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Team as json to create a new Team.", required = true) + @RequestBody TeamDto teamDto) { Team createdTeam = teamAuthorizationService.createEntity(teamMapper.toTeam(teamDto)); return ResponseEntity.status(HttpStatus.CREATED).body(teamMapper.toDto(createdTeam)); } @@ -59,9 +58,8 @@ public ResponseEntity createTeam( @ApiResponse(responseCode = "404", description = "Did not find a Team with a specified ID to update.", content = @Content), @ApiResponse(responseCode = "422", description = "Can't update Team since Team was updated or deleted by another user.", content = @Content) }) @PutMapping("/{id}") - public ResponseEntity updateTeam( - @Parameter(description = "The ID for updating a Team.", required = true) @PathVariable long id, - @RequestBody TeamDto teamDto) { + public ResponseEntity updateTeam(@Parameter(description = "The ID for updating a Team.", required = true) + @PathVariable long id, @RequestBody TeamDto teamDto) { Team updatedTeam = teamAuthorizationService.updateEntity(teamMapper.toTeam(teamDto), id); return ResponseEntity.status(OK).body(teamMapper.toDto(updatedTeam)); } @@ -71,8 +69,8 @@ public ResponseEntity updateTeam( @ApiResponse(responseCode = "401", description = "Not authorized to delete an Team", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Team with requested ID") }) @DeleteMapping("/{id}") - public void deleteTeamById( - @Parameter(description = "The ID of an Team to delete it.", required = true) @PathVariable long id) { + public void deleteTeamById(@Parameter(description = "The ID of an Team to delete it.", required = true) + @PathVariable long id) { teamAuthorizationService.deleteEntity(id); } @@ -81,9 +79,8 @@ public void deleteTeamById( @ApiResponse(responseCode = "401", description = "Not authorized to add users to the team", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Team with requested ID") }) @PutMapping("/{id}/addusers") - public void addUsersToTeam( - @Parameter(description = "The ID of an Team to add to users to it.", required = true) @PathVariable long id, - @RequestBody List userDtoList) { + public void addUsersToTeam(@Parameter(description = "The ID of an Team to add to users to it.", required = true) + @PathVariable long id, @RequestBody List userDtoList) { var userIds = userDtoList.stream().map(UserDto::id).toList(); teamAuthorizationService.addUsersToTeam(id, userIds); } @@ -93,22 +90,19 @@ public void addUsersToTeam( @ApiResponse(responseCode = "401", description = "Not authorized to remove user from team", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Team with requested ID") }) @PutMapping("/{id}/user/{userId}/removeuser") - public void removeUserFromTeam( - @Parameter(description = "The ID of an team to remove the user from it.", required = true) @PathVariable long id, - @Parameter(description = "The User ID to remove from the team.", required = true) @PathVariable long userId) { + public void removeUserFromTeam(@Parameter(description = "The ID of an team to remove the user from it.", required = true) + @PathVariable long id, @Parameter(description = "The User ID to remove from the team.", required = true) @PathVariable long userId) { teamAuthorizationService.removeUserFromTeam(id, userId); } @Operation(summary = "Update or add team membership", description = "If user is already member of this team, isAdmin is set. otherwise new team membership " - + "is added with isAdmin true or false") + + "is added with isAdmin true or false") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Update or add team membership"), @ApiResponse(responseCode = "401", description = "Not authorized to update or add team membership", content = @Content), @ApiResponse(responseCode = "404", description = "Did not find the Team with requested ID") }) @PutMapping("/{id}/user/{userId}/updateaddteammembership/{isAdmin}") - public void updateOrAddTeamMembership( - @Parameter(description = "The ID of an team to update or add membership", required = true) @PathVariable long id, - @Parameter(description = "The User ID to update or add membership", required = true) @PathVariable long userId, - @Parameter(description = "The parameter if user should be admin or not", required = true) @PathVariable boolean isAdmin) { + public void updateOrAddTeamMembership(@Parameter(description = "The ID of an team to update or add membership", required = true) + @PathVariable long id, @Parameter(description = "The User ID to update or add membership", required = true) @PathVariable long userId, @Parameter(description = "The parameter if user should be admin or not", required = true) @PathVariable boolean isAdmin) { teamAuthorizationService.updateOrAddTeamMembership(id, userId, isAdmin); } } diff --git a/backend/src/main/java/ch/puzzle/okr/controller/UserController.java b/backend/src/main/java/ch/puzzle/okr/controller/UserController.java index 961adb7c1c..36decfb050 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/UserController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/UserController.java @@ -12,9 +12,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.web.bind.annotation.*; - import java.util.List; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("api/v1/users") @@ -25,7 +24,7 @@ public class UserController { private final UserMapper userMapper; public UserController(UserAuthorizationService userAuthorizationService, AuthorizationService authorizationService, - UserMapper userMapper) { + UserMapper userMapper) { this.userAuthorizationService = userAuthorizationService; this.authorizationService = authorizationService; this.userMapper = userMapper; @@ -53,8 +52,8 @@ public UserDto getCurrentUser() { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned user", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UserDto.class)) }), }) @GetMapping(path = "/{id}") - public UserDto getUserById( - @Parameter(description = "The ID for requested user.", required = true) @PathVariable long id) { + public UserDto getUserById(@Parameter(description = "The ID for requested user.", required = true) + @PathVariable long id) { var user = this.userAuthorizationService.getById(id); return userMapper.toDto(user); } @@ -63,9 +62,8 @@ public UserDto getUserById( @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned user", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UserDto.class)) }), }) @PutMapping(path = "/{id}/isokrchampion/{isOkrChampion}") - public UserDto setOkrChampion( - @Parameter(description = "The ID for requested user.", required = true) @PathVariable long id, - @Parameter(description = "okrChampion property of user is set to this flag.", required = true) @PathVariable boolean isOkrChampion) { + public UserDto setOkrChampion(@Parameter(description = "The ID for requested user.", required = true) + @PathVariable long id, @Parameter(description = "okrChampion property of user is set to this flag.", required = true) @PathVariable boolean isOkrChampion) { var user = this.userAuthorizationService.setIsOkrChampion(id, isOkrChampion); return userMapper.toDto(user); } @@ -74,8 +72,8 @@ public UserDto setOkrChampion( @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned users", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = UserDto.class)) }), }) @PostMapping(path = "/createall") - public List createUsers( - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The users to create", required = true) @RequestBody List newUserDtoList) { + public List createUsers(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The users to create", required = true) + @RequestBody List newUserDtoList) { var createdUsers = this.userAuthorizationService.createUsers(userMapper.toUserList(newUserDtoList)); return userMapper.toDtos(createdUsers); } @@ -86,8 +84,8 @@ public List createUsers( @Content(mediaType = "application/json", schema = @Schema(implementation = Boolean.class)) }), }) @GetMapping(path = "/{id}/ismemberofteams") - public Boolean isUserMemberOfTeams( - @Parameter(description = "The ID of the user.", required = true) @PathVariable long id) { + public Boolean isUserMemberOfTeams(@Parameter(description = "The ID of the user.", required = true) + @PathVariable long id) { return this.userAuthorizationService.isUserMemberOfTeams(id); } diff --git a/backend/src/main/java/ch/puzzle/okr/deserializer/CheckInDeserializer.java b/backend/src/main/java/ch/puzzle/okr/deserializer/CheckInDeserializer.java index 5cf3d6406f..c4f9ffecad 100644 --- a/backend/src/main/java/ch/puzzle/okr/deserializer/CheckInDeserializer.java +++ b/backend/src/main/java/ch/puzzle/okr/deserializer/CheckInDeserializer.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.deserializer; +import static ch.puzzle.okr.Constants.*; + import ch.puzzle.okr.dto.checkin.*; import ch.puzzle.okr.service.business.KeyResultBusinessService; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; -import org.springframework.stereotype.Component; - import java.io.IOException; - -import static ch.puzzle.okr.Constants.*; +import org.springframework.stereotype.Component; @Component public class CheckInDeserializer extends JsonDeserializer implements MetricOrdinalDeserializer { @@ -17,7 +16,7 @@ public class CheckInDeserializer extends JsonDeserializer implements private final KeyResultBusinessService keyResultBusinessService; public CheckInDeserializer(DeserializerHelper deserializerHelper, - KeyResultBusinessService keyResultBusinessService) { + KeyResultBusinessService keyResultBusinessService) { this.deserializerHelper = deserializerHelper; this.keyResultBusinessService = keyResultBusinessService; } diff --git a/backend/src/main/java/ch/puzzle/okr/deserializer/DeserializerHelper.java b/backend/src/main/java/ch/puzzle/okr/deserializer/DeserializerHelper.java index b305a24da8..d908110618 100644 --- a/backend/src/main/java/ch/puzzle/okr/deserializer/DeserializerHelper.java +++ b/backend/src/main/java/ch/puzzle/okr/deserializer/DeserializerHelper.java @@ -3,18 +3,18 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ResponseStatusException; -import java.io.IOException; -import java.util.Map; - @Component public class DeserializerHelper { public T deserializeMetricOrdinal(JsonParser jsonParser, Map> validTypes, - MetricOrdinalDeserializer deserializer) throws IOException { + MetricOrdinalDeserializer deserializer) + throws IOException { ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec(); ObjectNode root = mapper.readTree(jsonParser); diff --git a/backend/src/main/java/ch/puzzle/okr/deserializer/KeyResultDeserializer.java b/backend/src/main/java/ch/puzzle/okr/deserializer/KeyResultDeserializer.java index 7515e14d7c..4cdbb7960c 100644 --- a/backend/src/main/java/ch/puzzle/okr/deserializer/KeyResultDeserializer.java +++ b/backend/src/main/java/ch/puzzle/okr/deserializer/KeyResultDeserializer.java @@ -1,13 +1,12 @@ package ch.puzzle.okr.deserializer; +import static ch.puzzle.okr.Constants.*; + import ch.puzzle.okr.dto.keyresult.KeyResultDto; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; - import java.io.IOException; -import static ch.puzzle.okr.Constants.*; - public class KeyResultDeserializer extends JsonDeserializer implements MetricOrdinalDeserializer { private final DeserializerHelper deserializerHelper; diff --git a/backend/src/main/java/ch/puzzle/okr/dto/DuplicateObjectiveDto.java b/backend/src/main/java/ch/puzzle/okr/dto/DuplicateObjectiveDto.java index d4f5bd7f8a..232fd14ae2 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/DuplicateObjectiveDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/DuplicateObjectiveDto.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.dto; import ch.puzzle.okr.dto.keyresult.KeyResultDto; - import java.util.List; public record DuplicateObjectiveDto(ObjectiveDto objective, List keyResults) { diff --git a/backend/src/main/java/ch/puzzle/okr/dto/ErrorDto.java b/backend/src/main/java/ch/puzzle/okr/dto/ErrorDto.java index 07ad03f1ae..4bd033c425 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/ErrorDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/ErrorDto.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.dto; import ch.puzzle.okr.ErrorKey; - import java.util.List; public record ErrorDto(String errorKey, List params) { diff --git a/backend/src/main/java/ch/puzzle/okr/dto/ObjectiveDto.java b/backend/src/main/java/ch/puzzle/okr/dto/ObjectiveDto.java index bf230fdcc8..9de9d8fafa 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/ObjectiveDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/ObjectiveDto.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.dto; import ch.puzzle.okr.models.State; - import java.time.LocalDateTime; public record ObjectiveDto(Long id, int version, String title, Long teamId, Long quarterId, String quarterLabel, diff --git a/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInMetricDto.java b/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInMetricDto.java index 03036b4cdd..190627334e 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInMetricDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInMetricDto.java @@ -1,11 +1,10 @@ package ch.puzzle.okr.dto.checkin; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.time.LocalDateTime; @JsonDeserialize(as = CheckInMetricDto.class) public record CheckInMetricDto(Long id, int version, String changeInfo, String initiatives, Integer confidence, - Long keyResultId, LocalDateTime createdOn, LocalDateTime modifiedOn, Double value, boolean writeable) - implements CheckInDto { + Long keyResultId, LocalDateTime createdOn, LocalDateTime modifiedOn, Double value, + boolean writeable) implements CheckInDto { } diff --git a/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInOrdinalDto.java b/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInOrdinalDto.java index 9bab43b985..d4537437f8 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInOrdinalDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/checkin/CheckInOrdinalDto.java @@ -2,11 +2,10 @@ import ch.puzzle.okr.models.checkin.Zone; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.time.LocalDateTime; @JsonDeserialize(as = CheckInOrdinalDto.class) public record CheckInOrdinalDto(Long id, int version, String changeInfo, String initiatives, Integer confidence, - Long keyResultId, LocalDateTime createdOn, LocalDateTime modifiedOn, Zone zone, boolean writeable) - implements CheckInDto { + Long keyResultId, LocalDateTime createdOn, LocalDateTime modifiedOn, Zone zone, + boolean writeable) implements CheckInDto { } diff --git a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultDto.java b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultDto.java index b461737716..95cfbc164e 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultDto.java @@ -3,7 +3,6 @@ import ch.puzzle.okr.deserializer.KeyResultDeserializer; import ch.puzzle.okr.dto.ActionDto; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.util.List; @JsonDeserialize(using = KeyResultDeserializer.class) diff --git a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultLastCheckInOrdinalDto.java b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultLastCheckInOrdinalDto.java index 92068a47a1..16bb51003f 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultLastCheckInOrdinalDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultLastCheckInOrdinalDto.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.dto.keyresult; import ch.puzzle.okr.models.checkin.Zone; - import java.time.LocalDateTime; public record KeyResultLastCheckInOrdinalDto(Long id, int version, Zone zone, Integer confidence, diff --git a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultMetricDto.java b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultMetricDto.java index b69b360f1d..69c0d18153 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultMetricDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultMetricDto.java @@ -3,7 +3,6 @@ import ch.puzzle.okr.dto.ActionDto; import ch.puzzle.okr.models.Unit; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultOrdinalDto.java b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultOrdinalDto.java index 4f0365b947..44d622ea35 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultOrdinalDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/keyresult/KeyResultOrdinalDto.java @@ -2,7 +2,6 @@ import ch.puzzle.okr.dto.ActionDto; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewKeyResultOrdinalDto.java b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewKeyResultOrdinalDto.java index 6097da2724..553fd0cbed 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewKeyResultOrdinalDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewKeyResultOrdinalDto.java @@ -1,6 +1,6 @@ package ch.puzzle.okr.dto.overview; public record OverviewKeyResultOrdinalDto(Long id, String title, String keyResultType, String commitZone, - String targetZone, String stretchZone, OverviewLastCheckInOrdinalDto lastCheckIn) - implements OverviewKeyResultDto { + String targetZone, String stretchZone, + OverviewLastCheckInOrdinalDto lastCheckIn) implements OverviewKeyResultDto { } diff --git a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInMetricDto.java b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInMetricDto.java index 94e15589d8..2338903704 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInMetricDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInMetricDto.java @@ -2,6 +2,6 @@ import java.time.LocalDateTime; -public record OverviewLastCheckInMetricDto(Long id, Double value, Integer confidence, LocalDateTime createdOn) - implements OverviewLastCheckInDto { +public record OverviewLastCheckInMetricDto(Long id, Double value, Integer confidence, + LocalDateTime createdOn) implements OverviewLastCheckInDto { } diff --git a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInOrdinalDto.java b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInOrdinalDto.java index 131d126373..e01f1a6781 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInOrdinalDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewLastCheckInOrdinalDto.java @@ -2,6 +2,6 @@ import java.time.LocalDateTime; -public record OverviewLastCheckInOrdinalDto(Long id, String zone, Integer confidence, LocalDateTime createdOn) - implements OverviewLastCheckInDto { +public record OverviewLastCheckInOrdinalDto(Long id, String zone, Integer confidence, + LocalDateTime createdOn) implements OverviewLastCheckInDto { } diff --git a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewObjectiveDto.java b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewObjectiveDto.java index 403a7073b6..e0f6ccc078 100644 --- a/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewObjectiveDto.java +++ b/backend/src/main/java/ch/puzzle/okr/dto/overview/OverviewObjectiveDto.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.dto.overview; import ch.puzzle.okr.models.State; - import java.util.List; public record OverviewObjectiveDto(Long id, String title, State state, OverviewQuarterDto quarter, diff --git a/backend/src/main/java/ch/puzzle/okr/exception/OkrResponseStatusException.java b/backend/src/main/java/ch/puzzle/okr/exception/OkrResponseStatusException.java index 11f666040e..712b292ecd 100644 --- a/backend/src/main/java/ch/puzzle/okr/exception/OkrResponseStatusException.java +++ b/backend/src/main/java/ch/puzzle/okr/exception/OkrResponseStatusException.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.exception; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.dto.ErrorDto; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - public class OkrResponseStatusException extends ResponseStatusException { private final List errors; diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/ActionMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/ActionMapper.java index 67d6d97e40..7be672faea 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/ActionMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/ActionMapper.java @@ -4,9 +4,8 @@ import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.business.KeyResultBusinessService; -import org.springframework.stereotype.Component; - import java.util.List; +import org.springframework.stereotype.Component; @Component public class ActionMapper { @@ -18,8 +17,13 @@ public ActionMapper(KeyResultBusinessService keyResultBusinessService) { } public ActionDto toDto(Action action) { - return new ActionDto(action.getId(), action.getVersion(), action.getAction(), action.getPriority(), - action.isChecked(), action.getKeyResult().getId(), action.isWriteable()); + return new ActionDto(action.getId(), + action.getVersion(), + action.getAction(), + action.getPriority(), + action.isChecked(), + action.getKeyResult().getId(), + action.isWriteable()); } public List toActions(List actionDtos, KeyResult keyResult) { @@ -27,14 +31,21 @@ public List toActions(List actionDtos, KeyResult keyResult) { } public List toActions(List actionDtos) { - return actionDtos.stream() + return actionDtos + .stream() .map(actionDto -> toAction(actionDto, keyResultBusinessService.getEntityById(actionDto.keyResultId()))) .toList(); } private Action toAction(ActionDto actionDto, KeyResult keyResult) { - return Action.Builder.builder().withId(actionDto.id()).withVersion(actionDto.version()) - .withAction(actionDto.action()).withPriority(actionDto.priority()).withIsChecked(actionDto.isChecked()) - .withKeyResult(keyResult).build(); + return Action.Builder + .builder() + .withId(actionDto.id()) + .withVersion(actionDto.version()) + .withAction(actionDto.action()) + .withPriority(actionDto.priority()) + .withIsChecked(actionDto.isChecked()) + .withKeyResult(keyResult) + .build(); } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/AlignmentSelectionMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/AlignmentSelectionMapper.java index 547181b95e..a19d82f6bb 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/AlignmentSelectionMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/AlignmentSelectionMapper.java @@ -3,12 +3,11 @@ import ch.puzzle.okr.dto.alignment.AlignmentKeyResultDto; import ch.puzzle.okr.dto.alignment.AlignmentObjectiveDto; import ch.puzzle.okr.models.alignment.AlignmentSelection; -import org.springframework.stereotype.Component; - import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; +import org.springframework.stereotype.Component; @Component public class AlignmentSelectionMapper { @@ -20,13 +19,14 @@ public List toDto(List alignments) { } private Optional getMatchingObjectiveDto(Long objectiveId, - List objectives) { + List objectives) { return objectives.stream().filter(objectiveDto -> Objects.equals(objectiveId, objectiveDto.id())).findFirst(); } private void processObjectives(List objectiveDtos, AlignmentSelection alignment) { - Optional objectiveDto = getMatchingObjectiveDto( - alignment.getAlignmentSelectionId().getObjectiveId(), objectiveDtos); + Optional objectiveDto = getMatchingObjectiveDto(alignment + .getAlignmentSelectionId() + .getObjectiveId(), objectiveDtos); if (objectiveDto.isPresent()) { processKeyResults(objectiveDto.get(), alignment); } else { @@ -44,12 +44,13 @@ private void processKeyResults(AlignmentObjectiveDto objectiveDto, AlignmentSele private AlignmentObjectiveDto createObjectiveDto(AlignmentSelection alignment) { return new AlignmentObjectiveDto(alignment.getAlignmentSelectionId().getObjectiveId(), - alignment.getObjectiveTitle(), new ArrayList<>()); + alignment.getObjectiveTitle(), + new ArrayList<>()); } private AlignmentKeyResultDto createKeyResultDto(AlignmentSelection alignment) { return new AlignmentKeyResultDto(alignment.getAlignmentSelectionId().getKeyResultId(), - alignment.getKeyResultTitle()); + alignment.getKeyResultTitle()); } private boolean isValidId(Long id) { diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/CompletedMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/CompletedMapper.java index fec0b71b93..53e29e39cc 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/CompletedMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/CompletedMapper.java @@ -15,13 +15,14 @@ public CompletedMapper(ObjectiveMapper objectiveMapper) { public CompletedDto toDto(Completed completed) { return new CompletedDto( // - completed.getId(), // - objectiveMapper.toDto(completed.getObjective()), // - completed.getComment()); + completed.getId(), // + objectiveMapper.toDto(completed.getObjective()), // + completed.getComment()); } public Completed toCompleted(CompletedDto completedDto) { - return Completed.Builder.builder() // + return Completed.Builder + .builder() // .withId(completedDto.id()) // .withObjective(objectiveMapper.toObjective(completedDto.objective())) // .withComment(completedDto.comment()) // diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/ObjectiveMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/ObjectiveMapper.java index a65574c408..1334d6d663 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/ObjectiveMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/ObjectiveMapper.java @@ -4,9 +4,8 @@ import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.service.business.QuarterBusinessService; import ch.puzzle.okr.service.business.TeamBusinessService; -import org.springframework.stereotype.Component; - import java.time.LocalDateTime; +import org.springframework.stereotype.Component; @Component public class ObjectiveMapper { @@ -20,17 +19,31 @@ public ObjectiveMapper(TeamBusinessService teamBusinessService, QuarterBusinessS } public ObjectiveDto toDto(Objective objective) { - return new ObjectiveDto(objective.getId(), objective.getVersion(), objective.getTitle(), - objective.getTeam().getId(), objective.getQuarter().getId(), objective.getQuarter().getLabel(), - objective.getDescription(), objective.getState(), objective.getCreatedOn(), objective.getModifiedOn(), - objective.isWriteable()); + return new ObjectiveDto(objective.getId(), + objective.getVersion(), + objective.getTitle(), + objective.getTeam().getId(), + objective.getQuarter().getId(), + objective.getQuarter().getLabel(), + objective.getDescription(), + objective.getState(), + objective.getCreatedOn(), + objective.getModifiedOn(), + objective.isWriteable()); } public Objective toObjective(ObjectiveDto objectiveDto) { - return Objective.Builder.builder().withId(objectiveDto.id()).withVersion(objectiveDto.version()) - .withTitle(objectiveDto.title()).withTeam(teamBusinessService.getTeamById(objectiveDto.teamId())) - .withDescription(objectiveDto.description()).withModifiedOn(LocalDateTime.now()) - .withState(objectiveDto.state()).withCreatedOn(objectiveDto.createdOn()) - .withQuarter(quarterBusinessService.getQuarterById(objectiveDto.quarterId())).build(); + return Objective.Builder + .builder() + .withId(objectiveDto.id()) + .withVersion(objectiveDto.version()) + .withTitle(objectiveDto.title()) + .withTeam(teamBusinessService.getTeamById(objectiveDto.teamId())) + .withDescription(objectiveDto.description()) + .withModifiedOn(LocalDateTime.now()) + .withState(objectiveDto.state()) + .withCreatedOn(objectiveDto.createdOn()) + .withQuarter(quarterBusinessService.getQuarterById(objectiveDto.quarterId())) + .build(); } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/OverviewMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/OverviewMapper.java index 2051b17b89..5a3a0959cd 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/OverviewMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/OverviewMapper.java @@ -1,19 +1,18 @@ package ch.puzzle.okr.mapper; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.dto.overview.*; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.overview.Overview; -import org.springframework.stereotype.Component; - import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; -import static org.springframework.http.HttpStatus.BAD_REQUEST; +import org.springframework.stereotype.Component; @Component public class OverviewMapper { @@ -31,7 +30,7 @@ private Optional getMatchingOverviewDto(Long teamId, List getMatchingObjectiveDto(Long objectiveId, - List objectives) { + List objectives) { return objectives.stream().filter(objectiveDto -> Objects.equals(objectiveId, objectiveDto.id())).findFirst(); } @@ -45,8 +44,9 @@ private void processTeams(List overviewDtos, Overview overview) { } private void processObjectives(OverviewDto overviewDto, Overview overview) { - Optional overviewObjectiveDto = getMatchingObjectiveDto( - overview.getOverviewId().getObjectiveId(), overviewDto.objectives()); + Optional overviewObjectiveDto = getMatchingObjectiveDto(overview + .getOverviewId() + .getObjectiveId(), overviewDto.objectives()); if (overviewObjectiveDto.isPresent()) { processKeyResults(overviewObjectiveDto.get(), overview); } else { @@ -64,7 +64,8 @@ private OverviewDto createOverviewDto(Overview overview) { objectives.add(createObjectiveDto(overview)); } return new OverviewDto(new OverviewTeamDto(overview.getOverviewId().getTeamId(), overview.getTeamName()), - objectives, overview.isWriteable()); + objectives, + overview.isWriteable()); } private OverviewObjectiveDto createObjectiveDto(Overview overview) { @@ -72,9 +73,11 @@ private OverviewObjectiveDto createObjectiveDto(Overview overview) { if (isValidId(overview.getOverviewId().getKeyResultId())) { keyResults.add(createKeyResultDto(overview)); } - return new OverviewObjectiveDto(overview.getOverviewId().getObjectiveId(), overview.getObjectiveTitle(), - overview.getObjectiveState(), - new OverviewQuarterDto(overview.getQuarterId(), overview.getQuarterLabel()), keyResults); + return new OverviewObjectiveDto(overview.getOverviewId().getObjectiveId(), + overview.getObjectiveTitle(), + overview.getObjectiveState(), + new OverviewQuarterDto(overview.getQuarterId(), overview.getQuarterLabel()), + keyResults); } private OverviewKeyResultDto createKeyResultDto(Overview overview) { @@ -83,8 +86,9 @@ private OverviewKeyResultDto createKeyResultDto(Overview overview) { } else if (Objects.equals(overview.getKeyResultType(), KEY_RESULT_TYPE_ORDINAL)) { return createKeyResultOrdinalDto(overview); } else { - throw new OkrResponseStatusException(BAD_REQUEST, ErrorKey.KEY_RESULT_CONVERSION, - overview.getKeyResultType()); + throw new OkrResponseStatusException(BAD_REQUEST, + ErrorKey.KEY_RESULT_CONVERSION, + overview.getKeyResultType()); } } @@ -92,22 +96,34 @@ private OverviewKeyResultMetricDto createKeyResultMetricDto(Overview overview) { OverviewLastCheckInMetricDto lastCheckIn = null; if (isValidId(overview.getOverviewId().getCheckInId())) { lastCheckIn = new OverviewLastCheckInMetricDto(overview.getOverviewId().getCheckInId(), - overview.getCheckInValue(), overview.getConfidence(), overview.getCheckInCreatedOn()); + overview.getCheckInValue(), + overview.getConfidence(), + overview.getCheckInCreatedOn()); } - return new OverviewKeyResultMetricDto(overview.getOverviewId().getKeyResultId(), overview.getKeyResultTitle(), - overview.getKeyResultType(), overview.getUnit(), overview.getBaseline(), overview.getStretchGoal(), - lastCheckIn); + return new OverviewKeyResultMetricDto(overview.getOverviewId().getKeyResultId(), + overview.getKeyResultTitle(), + overview.getKeyResultType(), + overview.getUnit(), + overview.getBaseline(), + overview.getStretchGoal(), + lastCheckIn); } private OverviewKeyResultOrdinalDto createKeyResultOrdinalDto(Overview overview) { OverviewLastCheckInOrdinalDto lastCheckIn = null; if (isValidId(overview.getOverviewId().getCheckInId())) { lastCheckIn = new OverviewLastCheckInOrdinalDto(overview.getOverviewId().getCheckInId(), - overview.getCheckInZone(), overview.getConfidence(), overview.getCheckInCreatedOn()); + overview.getCheckInZone(), + overview.getConfidence(), + overview.getCheckInCreatedOn()); } - return new OverviewKeyResultOrdinalDto(overview.getOverviewId().getKeyResultId(), overview.getKeyResultTitle(), - overview.getKeyResultType(), overview.getCommitZone(), overview.getTargetZone(), - overview.getStretchZone(), lastCheckIn); + return new OverviewKeyResultOrdinalDto(overview.getOverviewId().getKeyResultId(), + overview.getKeyResultTitle(), + overview.getKeyResultType(), + overview.getCommitZone(), + overview.getTargetZone(), + overview.getStretchZone(), + lastCheckIn); } private boolean isValidId(Long id) { diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/TeamMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/TeamMapper.java index 792bc027e6..2f9f48005b 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/TeamMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/TeamMapper.java @@ -15,7 +15,11 @@ public TeamDto toDto(Team team) { } public Team toTeam(TeamDto teamDto) { - return Team.Builder.builder().withId(teamDto.id()).withVersion(teamDto.version()).withName(teamDto.name()) + return Team.Builder + .builder() + .withId(teamDto.id()) + .withVersion(teamDto.version()) + .withName(teamDto.name()) .build(); } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java index 8d2f3c1892..6ad179fd5d 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java @@ -4,10 +4,9 @@ import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.dto.UserTeamDto; import ch.puzzle.okr.models.User; -import org.springframework.stereotype.Component; - import java.util.List; import java.util.stream.Collectors; +import org.springframework.stereotype.Component; @Component public class UserMapper { @@ -23,12 +22,22 @@ public List toDtos(List userList) { } public UserDto toDto(User user) { - var userTeams = user.getUserTeamList().stream().map( - ut -> new UserTeamDto(ut.getId(), user.getVersion(), teamMapper.toDto(ut.getTeam()), ut.isTeamAdmin())) + var userTeams = user + .getUserTeamList() + .stream() + .map(ut -> new UserTeamDto(ut.getId(), + user.getVersion(), + teamMapper.toDto(ut.getTeam()), + ut.isTeamAdmin())) .collect(Collectors.toList()); - return new UserDto(user.getId(), user.getVersion(), user.getFirstname(), user.getLastname(), user.getEmail(), - userTeams, user.isOkrChampion()); + return new UserDto(user.getId(), + user.getVersion(), + user.getFirstname(), + user.getLastname(), + user.getEmail(), + userTeams, + user.isOkrChampion()); } public List toUserList(List newUserList) { diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/UserOkrDataMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/UserOkrDataMapper.java index 88fc383bf2..0b4a411c15 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/UserOkrDataMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/UserOkrDataMapper.java @@ -3,9 +3,8 @@ import ch.puzzle.okr.dto.userOkrData.UserKeyResultDataDto; import ch.puzzle.okr.dto.userOkrData.UserOkrDataDto; import ch.puzzle.okr.models.keyresult.KeyResult; -import org.springframework.stereotype.Component; - import java.util.List; +import org.springframework.stereotype.Component; @Component public class UserOkrDataMapper { @@ -15,10 +14,13 @@ public UserOkrDataDto toDto(List keyResults) { } private List toUserKeyResultDataDtos(List keyResults) { - return keyResults.stream() // + return keyResults + .stream() // .map(keyResult -> new UserKeyResultDataDto( // - keyResult.getId(), keyResult.getTitle(), // - keyResult.getObjective().getId(), keyResult.getObjective().getTitle() // + keyResult.getId(), + keyResult.getTitle(), // + keyResult.getObjective().getId(), + keyResult.getObjective().getTitle() // )) // .toList(); } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMapper.java index 34ab137035..e6a0642fac 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMapper.java @@ -27,7 +27,9 @@ public CheckInDto toDto(CheckIn checkIn) { return checkInOrdinalMapper.toDto(checkInOrdinal); } else { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - String.format("The CheckIn %s can't be converted to a metric or ordinal CheckIn", checkIn)); + String + .format("The CheckIn %s can't be converted to a metric or ordinal CheckIn", + checkIn)); } } @@ -38,7 +40,9 @@ public CheckIn toCheckIn(CheckInDto checkInDto) { return checkInOrdinalMapper.toCheckInOrdinal((CheckInOrdinalDto) checkInDto); } else { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - String.format("The provided CheckInDto %s is neither metric nor ordinal", checkInDto)); + String + .format("The provided CheckInDto %s is neither metric nor ordinal", + checkInDto)); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapper.java index 814adc85f2..fcf153ae06 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapper.java @@ -16,19 +16,20 @@ public CheckInMetricMapper(KeyResultBusinessService keyResultBusinessService) { public CheckInMetricDto toDto(CheckInMetric checkInMetric) { return new CheckInMetricDto(checkInMetric.getId(), // - checkInMetric.getVersion(), // - checkInMetric.getChangeInfo(), // - checkInMetric.getInitiatives(), // - checkInMetric.getConfidence(), // - checkInMetric.getKeyResult().getId(), // - checkInMetric.getCreatedOn(), // - checkInMetric.getModifiedOn(), // - checkInMetric.getValue(), // - checkInMetric.isWriteable()); + checkInMetric.getVersion(), // + checkInMetric.getChangeInfo(), // + checkInMetric.getInitiatives(), // + checkInMetric.getConfidence(), // + checkInMetric.getKeyResult().getId(), // + checkInMetric.getCreatedOn(), // + checkInMetric.getModifiedOn(), // + checkInMetric.getValue(), // + checkInMetric.isWriteable()); } public CheckIn toCheckInMetric(CheckInMetricDto checkInMetricDto) { - return CheckInMetric.Builder.builder() // + return CheckInMetric.Builder + .builder() // .withValue(checkInMetricDto.value()) // .withId(checkInMetricDto.id()) // .withVersion(checkInMetricDto.version()) // diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapper.java index 5bc4f811b8..da32c06a86 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapper.java @@ -15,19 +15,21 @@ public CheckInOrdinalMapper(KeyResultBusinessService keyResultBusinessService) { } public CheckInOrdinalDto toDto(CheckInOrdinal checkInOrdinal) { - return new CheckInOrdinalDto(checkInOrdinal.getId(), checkInOrdinal.getVersion(), // - checkInOrdinal.getChangeInfo(), // - checkInOrdinal.getInitiatives(), // - checkInOrdinal.getConfidence(), // - checkInOrdinal.getKeyResult().getId(), // - checkInOrdinal.getCreatedOn(), // - checkInOrdinal.getModifiedOn(), // - checkInOrdinal.getZone(), // - checkInOrdinal.isWriteable()); + return new CheckInOrdinalDto(checkInOrdinal.getId(), + checkInOrdinal.getVersion(), // + checkInOrdinal.getChangeInfo(), // + checkInOrdinal.getInitiatives(), // + checkInOrdinal.getConfidence(), // + checkInOrdinal.getKeyResult().getId(), // + checkInOrdinal.getCreatedOn(), // + checkInOrdinal.getModifiedOn(), // + checkInOrdinal.getZone(), // + checkInOrdinal.isWriteable()); } public CheckIn toCheckInOrdinal(CheckInOrdinalDto checkInOrdinalDto) { - return CheckInOrdinal.Builder.builder() // + return CheckInOrdinal.Builder + .builder() // .withZone(checkInOrdinalDto.zone()) // .withId(checkInOrdinalDto.id()) // .withVersion(checkInOrdinalDto.version()) // diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapper.java index 9078dbd04d..2f9434045f 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapper.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.mapper.keyresult; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.dto.keyresult.KeyResultMetricDto; import ch.puzzle.okr.dto.keyresult.KeyResultOrdinalDto; @@ -7,13 +9,10 @@ import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; +import java.util.List; import org.springframework.stereotype.Component; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @Component public class KeyResultMapper { @@ -32,7 +31,9 @@ public KeyResultDto toDto(KeyResult keyResult, List actionList) { return keyResultOrdinalMapper.toDto(keyResultOrdinal, actionList); } else { throw new ResponseStatusException(BAD_REQUEST, - String.format("The KeyResult %s can't be converted to a metric or ordinal KeyResult", keyResult)); + String + .format("The KeyResult %s can't be converted to a metric or ordinal KeyResult", + keyResult)); } } @@ -43,7 +44,9 @@ public KeyResult toKeyResult(KeyResultDto keyResultDto) { return keyResultOrdinalMapper.toKeyResultOrdinal((KeyResultOrdinalDto) keyResultDto); } else { throw new ResponseStatusException(BAD_REQUEST, - String.format("The provided KeyResultDto %s is neither metric nor ordinal", keyResultDto)); + String + .format("The provided KeyResultDto %s is neither metric nor ordinal", + keyResultDto)); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapper.java index e285304f06..e84d2520ef 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapper.java @@ -10,9 +10,8 @@ import ch.puzzle.okr.service.business.CheckInBusinessService; import ch.puzzle.okr.service.business.ObjectiveBusinessService; import ch.puzzle.okr.service.business.UserBusinessService; -import org.springframework.stereotype.Component; - import java.util.List; +import org.springframework.stereotype.Component; @Component public class KeyResultMetricMapper { @@ -23,8 +22,8 @@ public class KeyResultMetricMapper { private final ActionMapper actionMapper; public KeyResultMetricMapper(UserBusinessService userBusinessService, - ObjectiveBusinessService objectiveBusinessService, CheckInBusinessService checkInBusinessService, - ActionMapper actionMapper) { + ObjectiveBusinessService objectiveBusinessService, + CheckInBusinessService checkInBusinessService, ActionMapper actionMapper) { this.userBusinessService = userBusinessService; this.objectiveBusinessService = objectiveBusinessService; this.checkInBusinessService = checkInBusinessService; @@ -33,42 +32,44 @@ public KeyResultMetricMapper(UserBusinessService userBusinessService, public KeyResultDto toDto(KeyResultMetric keyResult, List actionList) { KeyResultUserDto ownerDto = new KeyResultUserDto( // - keyResult.getOwner().getId(), // - keyResult.getOwner().getFirstname(), // - keyResult.getOwner().getLastname()); + keyResult.getOwner().getId(), // + keyResult.getOwner().getFirstname(), // + keyResult.getOwner().getLastname()); KeyResultQuarterDto quarterDto = new KeyResultQuarterDto( // - keyResult.getObjective().getQuarter().getId(), // - keyResult.getObjective().getQuarter().getLabel(), // - keyResult.getObjective().getQuarter().getStartDate(), // - keyResult.getObjective().getQuarter().getEndDate()); + keyResult.getObjective().getQuarter().getId(), // + keyResult.getObjective().getQuarter().getLabel(), // + keyResult.getObjective().getQuarter().getStartDate(), // + keyResult.getObjective().getQuarter().getEndDate()); KeyResultObjectiveDto objectiveDto = new KeyResultObjectiveDto( // - keyResult.getObjective().getId(), // - keyResult.getObjective().getState().toString(), // - quarterDto); + keyResult.getObjective().getId(), // + keyResult.getObjective().getState().toString(), // + quarterDto); KeyResultLastCheckInMetricDto lastCheckInDto = getLastCheckInDto(keyResult.getId()); return new KeyResultMetricDto( // - keyResult.getId(), // - keyResult.getVersion(), // - keyResult.getKeyResultType(), // - keyResult.getTitle(), // - keyResult.getDescription(), // - keyResult.getBaseline(), // - keyResult.getStretchGoal(), // - keyResult.getUnit(), // - ownerDto, objectiveDto, // - lastCheckInDto, // - keyResult.getCreatedOn(), // - keyResult.getModifiedOn(), // - keyResult.isWriteable(), // - actionList.stream().map(actionMapper::toDto).toList()); + keyResult.getId(), // + keyResult.getVersion(), // + keyResult.getKeyResultType(), // + keyResult.getTitle(), // + keyResult.getDescription(), // + keyResult.getBaseline(), // + keyResult.getStretchGoal(), // + keyResult.getUnit(), // + ownerDto, + objectiveDto, // + lastCheckInDto, // + keyResult.getCreatedOn(), // + keyResult.getModifiedOn(), // + keyResult.isWriteable(), // + actionList.stream().map(actionMapper::toDto).toList()); } public KeyResult toKeyResultMetric(KeyResultMetricDto keyResultMetricDto) { - return KeyResultMetric.Builder.builder() // + return KeyResultMetric.Builder + .builder() // .withBaseline(keyResultMetricDto.baseline()) // .withStretchGoal(keyResultMetricDto.stretchGoal()) // .withUnit(keyResultMetricDto.unit()) // @@ -88,8 +89,12 @@ public KeyResultLastCheckInMetricDto getLastCheckInDto(Long keyResultId) { if (lastCheckIn == null) { return null; } - return new KeyResultLastCheckInMetricDto(lastCheckIn.getId(), lastCheckIn.getVersion(), - ((CheckInMetric) lastCheckIn).getValue(), lastCheckIn.getConfidence(), lastCheckIn.getCreatedOn(), - lastCheckIn.getChangeInfo(), lastCheckIn.getInitiatives()); + return new KeyResultLastCheckInMetricDto(lastCheckIn.getId(), + lastCheckIn.getVersion(), + ((CheckInMetric) lastCheckIn).getValue(), + lastCheckIn.getConfidence(), + lastCheckIn.getCreatedOn(), + lastCheckIn.getChangeInfo(), + lastCheckIn.getInitiatives()); } } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapper.java index e62c93b482..1e7f286e2c 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapper.java @@ -10,9 +10,8 @@ import ch.puzzle.okr.service.business.CheckInBusinessService; import ch.puzzle.okr.service.business.ObjectiveBusinessService; import ch.puzzle.okr.service.business.UserBusinessService; -import org.springframework.stereotype.Component; - import java.util.List; +import org.springframework.stereotype.Component; @Component public class KeyResultOrdinalMapper { @@ -23,8 +22,8 @@ public class KeyResultOrdinalMapper { private final ActionMapper actionMapper; public KeyResultOrdinalMapper(UserBusinessService userBusinessService, - ObjectiveBusinessService objectiveBusinessService, CheckInBusinessService checkInBusinessService, - ActionMapper actionMapper) { + ObjectiveBusinessService objectiveBusinessService, + CheckInBusinessService checkInBusinessService, ActionMapper actionMapper) { this.userBusinessService = userBusinessService; this.objectiveBusinessService = objectiveBusinessService; this.checkInBusinessService = checkInBusinessService; @@ -33,43 +32,44 @@ public KeyResultOrdinalMapper(UserBusinessService userBusinessService, public KeyResultDto toDto(KeyResultOrdinal keyResult, List actionList) { KeyResultUserDto ownerDto = new KeyResultUserDto( // - keyResult.getOwner().getId(), // - keyResult.getOwner().getFirstname(), // - keyResult.getOwner().getLastname()); + keyResult.getOwner().getId(), // + keyResult.getOwner().getFirstname(), // + keyResult.getOwner().getLastname()); KeyResultQuarterDto quarterDto = new KeyResultQuarterDto( // - keyResult.getObjective().getQuarter().getId(), // - keyResult.getObjective().getQuarter().getLabel(), // - keyResult.getObjective().getQuarter().getStartDate(), // - keyResult.getObjective().getQuarter().getEndDate()); + keyResult.getObjective().getQuarter().getId(), // + keyResult.getObjective().getQuarter().getLabel(), // + keyResult.getObjective().getQuarter().getStartDate(), // + keyResult.getObjective().getQuarter().getEndDate()); KeyResultObjectiveDto objectiveDto = new KeyResultObjectiveDto( // - keyResult.getObjective().getId(), // - keyResult.getObjective().getState().toString(), // - quarterDto); + keyResult.getObjective().getId(), // + keyResult.getObjective().getState().toString(), // + quarterDto); KeyResultLastCheckInOrdinalDto lastCheckInDto = getLastCheckInDto(keyResult.getId()); return new KeyResultOrdinalDto( // - keyResult.getId(), // - keyResult.getVersion(), // - keyResult.getKeyResultType(), // - keyResult.getTitle(), // - keyResult.getDescription(), // - keyResult.getCommitZone(), // - keyResult.getTargetZone(), // - keyResult.getStretchZone(), // - ownerDto, // - objectiveDto, // - lastCheckInDto, // - keyResult.getCreatedOn(), // - keyResult.getModifiedOn(), // - keyResult.isWriteable(), // - actionList.stream().map(actionMapper::toDto).toList()); + keyResult.getId(), // + keyResult.getVersion(), // + keyResult.getKeyResultType(), // + keyResult.getTitle(), // + keyResult.getDescription(), // + keyResult.getCommitZone(), // + keyResult.getTargetZone(), // + keyResult.getStretchZone(), // + ownerDto, // + objectiveDto, // + lastCheckInDto, // + keyResult.getCreatedOn(), // + keyResult.getModifiedOn(), // + keyResult.isWriteable(), // + actionList.stream().map(actionMapper::toDto).toList()); } public KeyResult toKeyResultOrdinal(KeyResultOrdinalDto keyResultOrdinalDto) { - return KeyResultOrdinal.Builder.builder() // + return KeyResultOrdinal.Builder + .builder() // .withCommitZone(keyResultOrdinalDto.commitZone()) // .withTargetZone(keyResultOrdinalDto.targetZone()) // .withStretchZone(keyResultOrdinalDto.stretchZone()) // @@ -89,8 +89,12 @@ public KeyResultLastCheckInOrdinalDto getLastCheckInDto(Long keyResultId) { if (lastCheckIn == null) { return null; } - return new KeyResultLastCheckInOrdinalDto(lastCheckIn.getId(), lastCheckIn.getVersion(), - ((CheckInOrdinal) lastCheckIn).getZone(), lastCheckIn.getConfidence(), lastCheckIn.getCreatedOn(), - lastCheckIn.getChangeInfo(), lastCheckIn.getInitiatives()); + return new KeyResultLastCheckInOrdinalDto(lastCheckIn.getId(), + lastCheckIn.getVersion(), + ((CheckInOrdinal) lastCheckIn).getZone(), + lastCheckIn.getConfidence(), + lastCheckIn.getCreatedOn(), + lastCheckIn.getChangeInfo(), + lastCheckIn.getInitiatives()); } } diff --git a/backend/src/main/java/ch/puzzle/okr/models/Action.java b/backend/src/main/java/ch/puzzle/okr/models/Action.java index eabed114da..793f7ec297 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Action.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Action.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models; import ch.puzzle.okr.models.keyresult.KeyResult; - import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -106,7 +105,7 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "Action{" + "id=" + id + ", version=" + version + ", action='" + action + '\'' + ", priority=" + priority - + ", isChecked=" + isChecked + ", keyResult=" + keyResult + ", writeable=" + writeable + '}'; + + ", isChecked=" + isChecked + ", keyResult=" + keyResult + ", writeable=" + writeable + '}'; } @Override @@ -117,8 +116,8 @@ public boolean equals(Object o) { return false; Action action1 = (Action) o; return version == action1.version && priority == action1.priority && isChecked == action1.isChecked - && writeable == action1.writeable && Objects.equals(id, action1.id) - && Objects.equals(action, action1.action) && Objects.equals(keyResult, action1.keyResult); + && writeable == action1.writeable && Objects.equals(id, action1.id) + && Objects.equals(action, action1.action) && Objects.equals(keyResult, action1.keyResult); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/Completed.java b/backend/src/main/java/ch/puzzle/okr/models/Completed.java index 7900c2910e..ea77c1d780 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Completed.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Completed.java @@ -59,7 +59,7 @@ public void setComment(String comment) { @Override public String toString() { return "Completed{" + "id=" + id + ", version=" + version + ", objective=" + objective + ", comment='" + comment - + '\'' + '}'; + + '\'' + '}'; } @Override @@ -70,7 +70,7 @@ public boolean equals(Object o) { return false; Completed completed = (Completed) o; return Objects.equals(id, completed.id) && version == completed.version - && Objects.equals(objective, completed.objective) && Objects.equals(comment, completed.comment); + && Objects.equals(objective, completed.objective) && Objects.equals(comment, completed.comment); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/Objective.java b/backend/src/main/java/ch/puzzle/okr/models/Objective.java index 85a96b59dd..99baa745db 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Objective.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Objective.java @@ -4,7 +4,6 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; - import java.time.LocalDateTime; import java.util.Objects; @@ -163,9 +162,9 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "Objective{" + "id=" + id + ", version=" + version + ", title='" + title + '\'' + ", createdBy=" - + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' - + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" - + modifiedBy + ", writeable=" + writeable + '\'' + '}'; + + createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\'' + + ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy=" + + modifiedBy + ", writeable=" + writeable + '\'' + '}'; } @Override @@ -176,17 +175,27 @@ public boolean equals(Object o) { return false; Objective objective = (Objective) o; return Objects.equals(id, objective.id) && version == objective.version - && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) - && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) - && Objects.equals(description, objective.description) - && Objects.equals(modifiedOn, objective.modifiedOn) && state == objective.state - && Objects.equals(createdOn, objective.createdOn) && Objects.equals(modifiedBy, objective.modifiedBy); + && Objects.equals(title, objective.title) && Objects.equals(createdBy, objective.createdBy) + && Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter) + && Objects.equals(description, objective.description) && Objects.equals(modifiedOn, objective.modifiedOn) + && state == objective.state && Objects.equals(createdOn, objective.createdOn) + && Objects.equals(modifiedBy, objective.modifiedBy); } @Override public int hashCode() { - return Objects.hash(id, version, title, createdBy, team, quarter, description, modifiedOn, state, createdOn, - modifiedBy); + return Objects + .hash(id, + version, + title, + createdBy, + team, + quarter, + description, + modifiedOn, + state, + createdOn, + modifiedBy); } public static final class Builder { diff --git a/backend/src/main/java/ch/puzzle/okr/models/Quarter.java b/backend/src/main/java/ch/puzzle/okr/models/Quarter.java index 537e0aa955..7c008cf3b3 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Quarter.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Quarter.java @@ -2,7 +2,6 @@ import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; - import java.time.LocalDate; import java.util.Objects; @@ -62,7 +61,7 @@ public void setEndDate(LocalDate endDate) { @Override public String toString() { return "Quarter{" + "id=" + id + ", label='" + label + '\'' + ", startDate=" + startDate + ", endDate=" - + endDate + '}'; + + endDate + '}'; } @Override @@ -73,7 +72,7 @@ public boolean equals(Object o) { return false; Quarter quarter = (Quarter) o; return Objects.equals(id, quarter.id) && Objects.equals(label, quarter.label) - && Objects.equals(startDate, quarter.startDate) && Objects.equals(endDate, quarter.endDate); + && Objects.equals(startDate, quarter.startDate) && Objects.equals(endDate, quarter.endDate); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/State.java b/backend/src/main/java/ch/puzzle/okr/models/State.java index 0099fcec97..5c12201a7e 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/State.java +++ b/backend/src/main/java/ch/puzzle/okr/models/State.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.models; public enum State { - SUCCESSFUL, NOTSUCCESSFUL, ONGOING, DRAFT + SUCCESSFUL, + NOTSUCCESSFUL, + ONGOING, + DRAFT } diff --git a/backend/src/main/java/ch/puzzle/okr/models/Team.java b/backend/src/main/java/ch/puzzle/okr/models/Team.java index 0099a9ba43..dd81ba7f35 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Team.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Team.java @@ -4,7 +4,6 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; - import java.util.List; import java.util.Objects; @@ -85,7 +84,7 @@ public boolean equals(Object o) { return false; Team team = (Team) o; return Objects.equals(id, team.id) && Objects.equals(version, team.version) && Objects.equals(name, team.name) - && Objects.equals(writeable, team.writeable); + && Objects.equals(writeable, team.writeable); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/Unit.java b/backend/src/main/java/ch/puzzle/okr/models/Unit.java index 13aff3bb47..941fb85f43 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/Unit.java +++ b/backend/src/main/java/ch/puzzle/okr/models/Unit.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.models; public enum Unit { - PERCENT, CHF, EUR, FTE, NUMBER + PERCENT, + CHF, + EUR, + FTE, + NUMBER } diff --git a/backend/src/main/java/ch/puzzle/okr/models/User.java b/backend/src/main/java/ch/puzzle/okr/models/User.java index 5bfa5e425b..e92d9b2e3d 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/User.java +++ b/backend/src/main/java/ch/puzzle/okr/models/User.java @@ -5,7 +5,6 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; - import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -109,7 +108,7 @@ public void setOkrChampion(boolean okrChampion) { @Override public String toString() { return "User{" + "id=" + id + ", version=" + version + ", firstname='" + firstname + '\'' + ", lastname='" - + lastname + '\'' + ", email='" + email + '\'' + ", isOkrChampion='" + isOkrChampion + '\'' + '}'; + + lastname + '\'' + ", email='" + email + '\'' + ", isOkrChampion='" + isOkrChampion + '\'' + '}'; } @Override @@ -120,8 +119,8 @@ public boolean equals(Object o) { return false; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(version, user.version) - && Objects.equals(firstname, user.firstname) && Objects.equals(lastname, user.lastname) - && Objects.equals(email, user.email) && Objects.equals(isOkrChampion, user.isOkrChampion); + && Objects.equals(firstname, user.firstname) && Objects.equals(lastname, user.lastname) + && Objects.equals(email, user.email) && Objects.equals(isOkrChampion, user.isOkrChampion); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/UserTeam.java b/backend/src/main/java/ch/puzzle/okr/models/UserTeam.java index 3f14e7c811..281f02faf6 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/UserTeam.java +++ b/backend/src/main/java/ch/puzzle/okr/models/UserTeam.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models; import jakarta.persistence.*; - import java.util.Objects; @Entity @@ -88,7 +87,7 @@ public boolean equals(Object o) { } UserTeam userTeam = (UserTeam) o; return version == userTeam.version && isTeamAdmin == userTeam.isTeamAdmin && Objects.equals(id, userTeam.id) - && Objects.equals(user, userTeam.user) && Objects.equals(team, userTeam.team); + && Objects.equals(user, userTeam.user) && Objects.equals(team, userTeam.team); } @Override @@ -99,7 +98,7 @@ public int hashCode() { @Override public String toString() { return "UserTeam{" + "id=" + id + ", version=" + version + ", user=" + user + ", team=" + team - + ", isTeamAdmin=" + isTeamAdmin + '}'; + + ", isTeamAdmin=" + isTeamAdmin + '}'; } public static class Builder { diff --git a/backend/src/main/java/ch/puzzle/okr/models/alignment/Alignment.java b/backend/src/main/java/ch/puzzle/okr/models/alignment/Alignment.java index cf3a64f7fc..2c6ae48992 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/alignment/Alignment.java +++ b/backend/src/main/java/ch/puzzle/okr/models/alignment/Alignment.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.alignment; import ch.puzzle.okr.models.Objective; - import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import java.util.Objects; @@ -59,7 +58,7 @@ public boolean equals(Object o) { return false; Alignment alignment = (Alignment) o; return Objects.equals(id, alignment.id) && version == alignment.version - && Objects.equals(alignedObjective, alignment.alignedObjective); + && Objects.equals(alignedObjective, alignment.alignedObjective); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelection.java b/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelection.java index 0246817184..562b5a4fc0 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelection.java +++ b/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelection.java @@ -2,9 +2,8 @@ import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; -import org.hibernate.annotations.Immutable; - import java.util.Objects; +import org.hibernate.annotations.Immutable; @Entity @Immutable @@ -61,10 +60,10 @@ public boolean equals(Object o) { return false; AlignmentSelection alignmentSelection = (AlignmentSelection) o; return Objects.equals(alignmentSelectionId, alignmentSelection.alignmentSelectionId) - && Objects.equals(teamId, alignmentSelection.teamId) - && Objects.equals(objectiveTitle, alignmentSelection.objectiveTitle) - && Objects.equals(quarterId, alignmentSelection.quarterId) - && Objects.equals(keyResultTitle, alignmentSelection.keyResultTitle); + && Objects.equals(teamId, alignmentSelection.teamId) + && Objects.equals(objectiveTitle, alignmentSelection.objectiveTitle) + && Objects.equals(quarterId, alignmentSelection.quarterId) + && Objects.equals(keyResultTitle, alignmentSelection.keyResultTitle); } @Override @@ -75,9 +74,9 @@ public int hashCode() { @Override public String toString() { return "AlignmentSelection{" + "alignmentSelectionId=" + alignmentSelectionId + ", teamId='" + teamId - + ", teamName='" + teamName + '\'' + ", objectiveTitle='" + objectiveTitle + '\'' + ", quarterId=" - + quarterId + ", quarterLabel='" + quarterLabel + '\'' + ", keyResultTitle='" + keyResultTitle + '\'' - + '}'; + + ", teamName='" + teamName + '\'' + ", objectiveTitle='" + objectiveTitle + '\'' + ", quarterId=" + + quarterId + ", quarterLabel='" + quarterLabel + '\'' + ", keyResultTitle='" + keyResultTitle + '\'' + + '}'; } public static final class Builder { diff --git a/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelectionId.java b/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelectionId.java index 75c52cf2b8..e99a7c5611 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelectionId.java +++ b/backend/src/main/java/ch/puzzle/okr/models/alignment/AlignmentSelectionId.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.alignment; import jakarta.persistence.Embeddable; - import java.io.Serializable; import java.util.Objects; diff --git a/backend/src/main/java/ch/puzzle/okr/models/alignment/KeyResultAlignment.java b/backend/src/main/java/ch/puzzle/okr/models/alignment/KeyResultAlignment.java index 1797ca005b..72ef8f21d7 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/alignment/KeyResultAlignment.java +++ b/backend/src/main/java/ch/puzzle/okr/models/alignment/KeyResultAlignment.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.alignment; import ch.puzzle.okr.models.keyresult.KeyResult; - import jakarta.persistence.*; import java.util.Objects; diff --git a/backend/src/main/java/ch/puzzle/okr/models/alignment/ObjectiveAlignment.java b/backend/src/main/java/ch/puzzle/okr/models/alignment/ObjectiveAlignment.java index f15422894f..7225c08176 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/alignment/ObjectiveAlignment.java +++ b/backend/src/main/java/ch/puzzle/okr/models/alignment/ObjectiveAlignment.java @@ -4,7 +4,6 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import jakarta.persistence.ManyToOne; - import java.util.Objects; @Entity diff --git a/backend/src/main/java/ch/puzzle/okr/models/authorization/AuthorizationUser.java b/backend/src/main/java/ch/puzzle/okr/models/authorization/AuthorizationUser.java index 829ba69765..a2acf2cc24 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/authorization/AuthorizationUser.java +++ b/backend/src/main/java/ch/puzzle/okr/models/authorization/AuthorizationUser.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.authorization; import ch.puzzle.okr.models.User; - import java.util.List; public record AuthorizationUser(User user) { @@ -14,7 +13,9 @@ public boolean isUserMemberInTeam(Long teamId) { } public boolean isUserAdminInTeam(Long teamId) { - return this.user.getUserTeamList().stream() + return this.user + .getUserTeamList() + .stream() .anyMatch(ut -> ut.isTeamAdmin() && ut.getTeam().getId().equals(teamId)); } } diff --git a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckIn.java b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckIn.java index 7105ca5950..8c408ff99b 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckIn.java +++ b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckIn.java @@ -4,10 +4,8 @@ import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.WriteableInterface; import ch.puzzle.okr.models.keyresult.KeyResult; - import jakarta.persistence.*; import jakarta.validation.constraints.*; - import java.time.LocalDateTime; import java.util.Objects; @@ -134,9 +132,9 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "CheckIn{" + "id=" + id + ", version=" + version + ", changeInfo='" + changeInfo + '\'' - + ", initiatives='" + initiatives + '\'' + ", confidence=" + confidence + ", keyResult=" + keyResult - + ", createdBy=" + createdBy + ", createdOn=" + createdOn + ", modifiedOn=" + modifiedOn - + ", checkInType='" + checkInType + '\'' + ", writeable=" + writeable + '\'' + '}'; + + ", initiatives='" + initiatives + '\'' + ", confidence=" + confidence + ", keyResult=" + keyResult + + ", createdBy=" + createdBy + ", createdOn=" + createdOn + ", modifiedOn=" + modifiedOn + + ", checkInType='" + checkInType + '\'' + ", writeable=" + writeable + '\'' + '}'; } @Override @@ -147,16 +145,25 @@ public boolean equals(Object o) { return false; CheckIn checkIn = (CheckIn) o; return Objects.equals(id, checkIn.id) && version == checkIn.version - && Objects.equals(changeInfo, checkIn.changeInfo) && Objects.equals(initiatives, checkIn.initiatives) - && Objects.equals(confidence, checkIn.confidence) && Objects.equals(keyResult, checkIn.keyResult) - && Objects.equals(createdBy, checkIn.createdBy) && Objects.equals(createdOn, checkIn.createdOn) - && Objects.equals(modifiedOn, checkIn.modifiedOn) && Objects.equals(checkInType, checkIn.checkInType); + && Objects.equals(changeInfo, checkIn.changeInfo) && Objects.equals(initiatives, checkIn.initiatives) + && Objects.equals(confidence, checkIn.confidence) && Objects.equals(keyResult, checkIn.keyResult) + && Objects.equals(createdBy, checkIn.createdBy) && Objects.equals(createdOn, checkIn.createdOn) + && Objects.equals(modifiedOn, checkIn.modifiedOn) && Objects.equals(checkInType, checkIn.checkInType); } @Override public int hashCode() { - return Objects.hash(id, version, changeInfo, initiatives, confidence, keyResult, createdBy, createdOn, - modifiedOn, checkInType); + return Objects + .hash(id, + version, + changeInfo, + initiatives, + confidence, + keyResult, + createdBy, + createdOn, + modifiedOn, + checkInType); } /* Constructor */ diff --git a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInMetric.java b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInMetric.java index 25faccff0e..b26834e455 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInMetric.java +++ b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInMetric.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.models.checkin; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; + import ch.puzzle.okr.models.MessageKey; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import jakarta.validation.constraints.NotNull; - import java.util.Objects; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; - @Entity @DiscriminatorValue(KEY_RESULT_TYPE_METRIC) public class CheckInMetric extends CheckIn { diff --git a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInOrdinal.java b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInOrdinal.java index 62485b5101..be7deba8e6 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInOrdinal.java +++ b/backend/src/main/java/ch/puzzle/okr/models/checkin/CheckInOrdinal.java @@ -1,16 +1,15 @@ package ch.puzzle.okr.models.checkin; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; + import ch.puzzle.okr.models.MessageKey; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import jakarta.validation.constraints.NotNull; - import java.util.Objects; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; - @Entity @DiscriminatorValue(KEY_RESULT_TYPE_ORDINAL) public class CheckInOrdinal extends CheckIn { diff --git a/backend/src/main/java/ch/puzzle/okr/models/checkin/Zone.java b/backend/src/main/java/ch/puzzle/okr/models/checkin/Zone.java index 79eec69420..4424418197 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/checkin/Zone.java +++ b/backend/src/main/java/ch/puzzle/okr/models/checkin/Zone.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.models.checkin; public enum Zone { - FAIL, COMMIT, TARGET, STRETCH + FAIL, + COMMIT, + TARGET, + STRETCH } diff --git a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResult.java b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResult.java index 1da614d05c..fa579e899c 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResult.java +++ b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResult.java @@ -4,7 +4,6 @@ import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.WriteableInterface; - import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -143,9 +142,9 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "KeyResult{" + "id=" + id + ", version=" + version + ", objective=" + objective + ", title='" + title - + '\'' + ", description='" + description + '\'' + ", owner=" + owner + ", createdBy=" + createdBy - + ", createdOn=" + createdOn + ", modifiedOn=" + modifiedOn + ", keyResultType='" + keyResultType - + ", writeable=" + writeable + '\'' + '}'; + + '\'' + ", description='" + description + '\'' + ", owner=" + owner + ", createdBy=" + createdBy + + ", createdOn=" + createdOn + ", modifiedOn=" + modifiedOn + ", keyResultType='" + keyResultType + + ", writeable=" + writeable + '\'' + '}'; } @Override @@ -156,17 +155,26 @@ public boolean equals(Object o) { return false; KeyResult keyResult = (KeyResult) o; return Objects.equals(id, keyResult.id) && version == keyResult.version - && Objects.equals(objective, keyResult.objective) && Objects.equals(title, keyResult.title) - && Objects.equals(description, keyResult.description) && Objects.equals(owner, keyResult.owner) - && Objects.equals(createdBy, keyResult.createdBy) && Objects.equals(createdOn, keyResult.createdOn) - && Objects.equals(modifiedOn, keyResult.modifiedOn) - && Objects.equals(keyResultType, keyResult.keyResultType); + && Objects.equals(objective, keyResult.objective) && Objects.equals(title, keyResult.title) + && Objects.equals(description, keyResult.description) && Objects.equals(owner, keyResult.owner) + && Objects.equals(createdBy, keyResult.createdBy) && Objects.equals(createdOn, keyResult.createdOn) + && Objects.equals(modifiedOn, keyResult.modifiedOn) + && Objects.equals(keyResultType, keyResult.keyResultType); } @Override public int hashCode() { - return Objects.hash(id, version, objective, title, description, owner, createdBy, createdOn, modifiedOn, - keyResultType); + return Objects + .hash(id, + version, + objective, + title, + description, + owner, + createdBy, + createdOn, + modifiedOn, + keyResultType); } protected KeyResult() { diff --git a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultMetric.java b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultMetric.java index 773501abc4..ece94d53f9 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultMetric.java +++ b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultMetric.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.models.keyresult; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; + import ch.puzzle.okr.models.MessageKey; import ch.puzzle.okr.models.Unit; - import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import java.util.Objects; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; - @Entity @DiscriminatorValue(KEY_RESULT_TYPE_METRIC) public class KeyResultMetric extends KeyResult { @@ -54,8 +53,8 @@ public KeyResultMetric() { public boolean equals(Object o) { if (o instanceof KeyResultMetric) { return super.equals(o) && Objects.equals(baseline, ((KeyResultMetric) o).baseline) - && Objects.equals(stretchGoal, ((KeyResultMetric) o).stretchGoal) - && Objects.equals(unit, ((KeyResultMetric) o).unit); + && Objects.equals(stretchGoal, ((KeyResultMetric) o).stretchGoal) + && Objects.equals(unit, ((KeyResultMetric) o).unit); } return false; } @@ -68,7 +67,7 @@ public int hashCode() { @Override public String toString() { return super.toString() + "KeyResultMetric{" + "baseline=" + baseline + ", stretchGoal=" + stretchGoal - + ", unit='" + unit + '\'' + '}'; + + ", unit='" + unit + '\'' + '}'; } private KeyResultMetric(Builder builder) { diff --git a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultOrdinal.java b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultOrdinal.java index d95f92a302..2f98b0e962 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultOrdinal.java +++ b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultOrdinal.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.models.keyresult; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; + import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; - import java.util.Objects; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; - @Entity @DiscriminatorValue(KEY_RESULT_TYPE_ORDINAL) public class KeyResultOrdinal extends KeyResult { @@ -56,8 +55,8 @@ public KeyResultOrdinal() { public boolean equals(Object o) { if (o instanceof KeyResultOrdinal) { return super.equals(o) && Objects.equals(commitZone, ((KeyResultOrdinal) o).commitZone) - && Objects.equals(targetZone, ((KeyResultOrdinal) o).targetZone) - && Objects.equals(stretchZone, ((KeyResultOrdinal) o).stretchZone); + && Objects.equals(targetZone, ((KeyResultOrdinal) o).targetZone) + && Objects.equals(stretchZone, ((KeyResultOrdinal) o).stretchZone); } return false; } @@ -70,7 +69,7 @@ public int hashCode() { @Override public String toString() { return super.toString() + "KeyResultOrdinal{" + "commitZone='" + commitZone + '\'' + ", targetZone='" - + targetZone + '\'' + ", stretchZone='" + stretchZone + '\'' + '}'; + + targetZone + '\'' + ", stretchZone='" + stretchZone + '\'' + '}'; } private KeyResultOrdinal(Builder builder) { diff --git a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultWithActionList.java b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultWithActionList.java index 1fae579ab3..2b0f367d53 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultWithActionList.java +++ b/backend/src/main/java/ch/puzzle/okr/models/keyresult/KeyResultWithActionList.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.keyresult; import ch.puzzle.okr.models.Action; - import java.util.List; public record KeyResultWithActionList(KeyResult keyResult, List actionList) { diff --git a/backend/src/main/java/ch/puzzle/okr/models/overview/Overview.java b/backend/src/main/java/ch/puzzle/okr/models/overview/Overview.java index b2b3eb6d79..303f400e81 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/overview/Overview.java +++ b/backend/src/main/java/ch/puzzle/okr/models/overview/Overview.java @@ -6,9 +6,8 @@ import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; -import org.hibernate.annotations.Immutable; - import java.time.LocalDateTime; +import org.hibernate.annotations.Immutable; @Entity @Immutable @@ -158,14 +157,14 @@ public void setWriteable(boolean writeable) { @Override public String toString() { return "Overview{" + "overviewId=" + overviewId + ", teamVersion='" + teamVersion + ", teamName='" + teamName - + '\'' + ", objectiveTitle='" + objectiveTitle + '\'' + ", objectiveState=" + objectiveState - + ", objectiveCreatedOn=" + objectiveCreatedOn + ", quarterId=" + quarterId + ", quarterLabel='" - + quarterLabel + '\'' + ", keyResultTitle='" + keyResultTitle + '\'' + ", keyResultType='" - + keyResultType + '\'' + ", baseline=" + baseline + ", stretchGoal=" + stretchGoal + ", unit='" + unit - + '\'' + ", commitZone='" + commitZone + '\'' + ", targetZone='" + targetZone + '\'' + ", stretchZone='" - + stretchZone + '\'' + ", checkInValue=" + checkInValue + ", checkInZone='" + checkInZone + '\'' - + ", confidence=" + confidence + ", createdOn=" + checkInCreatedOn + ", writeable=" + writeable + '\'' - + '}'; + + '\'' + ", objectiveTitle='" + objectiveTitle + '\'' + ", objectiveState=" + objectiveState + + ", objectiveCreatedOn=" + objectiveCreatedOn + ", quarterId=" + quarterId + ", quarterLabel='" + + quarterLabel + '\'' + ", keyResultTitle='" + keyResultTitle + '\'' + ", keyResultType='" + + keyResultType + '\'' + ", baseline=" + baseline + ", stretchGoal=" + stretchGoal + ", unit='" + unit + + '\'' + ", commitZone='" + commitZone + '\'' + ", targetZone='" + targetZone + '\'' + ", stretchZone='" + + stretchZone + '\'' + ", checkInValue=" + checkInValue + ", checkInZone='" + checkInZone + '\'' + + ", confidence=" + confidence + ", createdOn=" + checkInCreatedOn + ", writeable=" + writeable + '\'' + + '}'; } public static final class Builder { diff --git a/backend/src/main/java/ch/puzzle/okr/models/overview/OverviewId.java b/backend/src/main/java/ch/puzzle/okr/models/overview/OverviewId.java index 62bfb85e60..5923ba1808 100644 --- a/backend/src/main/java/ch/puzzle/okr/models/overview/OverviewId.java +++ b/backend/src/main/java/ch/puzzle/okr/models/overview/OverviewId.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.models.overview; import jakarta.persistence.Embeddable; - import java.io.Serializable; import java.util.Objects; @@ -50,7 +49,7 @@ public Long getCheckInId() { @Override public String toString() { return "OverviewId{" + "teamId=" + teamId + ", objectiveId=" + objectiveId + ", keyResultId=" + keyResultId - + ", checkInId=" + checkInId + '}'; + + ", checkInId=" + checkInId + '}'; } @Override @@ -61,7 +60,7 @@ public boolean equals(Object o) { return false; OverviewId that = (OverviewId) o; return Objects.equals(teamId, that.teamId) && Objects.equals(objectiveId, that.objectiveId) - && Objects.equals(keyResultId, that.keyResultId) && Objects.equals(checkInId, that.checkInId); + && Objects.equals(keyResultId, that.keyResultId) && Objects.equals(checkInId, that.checkInId); } @Override diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializer.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializer.java index d58c195c77..44a6801348 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializer.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializer.java @@ -11,7 +11,8 @@ public class FlywayMultitenantMigrationInitializer { private final String[] scriptLocations; public FlywayMultitenantMigrationInitializer(TenantConfigProviderInterface tenantConfigProvider, - final @Value("${spring.flyway.locations}") String[] scriptLocations) { + final @Value("${spring.flyway.locations}") + String[] scriptLocations) { this.tenantConfigProvider = tenantConfigProvider; this.scriptLocations = scriptLocations; } @@ -20,10 +21,11 @@ public void migrateFlyway() { this.tenantConfigProvider.getTenantConfigs().forEach((tenantConfig) -> { TenantConfigProvider.DataSourceConfig dataSourceConfig = this.tenantConfigProvider .getTenantConfigById(tenantConfig.tenantId()) - .map(TenantConfigProvider.TenantConfig::dataSourceConfig).orElseThrow( - () -> new EntityNotFoundException("Cannot find tenant for configuring flyway migration")); + .map(TenantConfigProvider.TenantConfig::dataSourceConfig) + .orElseThrow(() -> new EntityNotFoundException("Cannot find tenant for configuring flyway migration")); - Flyway tenantSchemaFlyway = Flyway.configure() // + Flyway tenantSchemaFlyway = Flyway + .configure() // .dataSource(dataSourceConfig.url(), dataSourceConfig.name(), dataSourceConfig.password()) // .locations(scriptLocations) // .baselineOnMigrate(Boolean.TRUE) // diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/HibernateContext.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/HibernateContext.java index 42e068ece0..d78c3ba4ac 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/HibernateContext.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/HibernateContext.java @@ -1,8 +1,7 @@ package ch.puzzle.okr.multitenancy; -import org.springframework.core.env.ConfigurableEnvironment; - import java.util.Properties; +import org.springframework.core.env.ConfigurableEnvironment; public class HibernateContext { public static final String HIBERNATE_CONNECTION_URL = "hibernate.connection.url"; diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProvider.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProvider.java index 05ff90ce53..7c8d2c0e01 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProvider.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProvider.java @@ -1,6 +1,12 @@ package ch.puzzle.okr.multitenancy; +import static ch.puzzle.okr.multitenancy.TenantContext.DEFAULT_TENANT_ID; + import ch.puzzle.okr.exception.ConnectionProviderException; +import java.sql.Connection; +import java.sql.SQLException; +import java.text.MessageFormat; +import java.util.*; import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider; @@ -8,13 +14,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Connection; -import java.sql.SQLException; -import java.text.MessageFormat; -import java.util.*; - -import static ch.puzzle.okr.multitenancy.TenantContext.DEFAULT_TENANT_ID; - public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider { private static final Logger logger = LoggerFactory.getLogger(SchemaMultiTenantConnectionProvider.class); @@ -55,24 +54,27 @@ protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) { } protected ConnectionProvider getConnectionProvider(String tenantIdentifier) { - return Optional.ofNullable(tenantIdentifier) // + return Optional + .ofNullable(tenantIdentifier) // .map(connectionProviderMap::get) // .orElseGet(() -> createNewConnectionProvider(tenantIdentifier)); } private ConnectionProvider createNewConnectionProvider(String tenantIdentifier) { - return Optional.ofNullable(tenantIdentifier) // + return Optional + .ofNullable(tenantIdentifier) // .map(this::createConnectionProvider) // .map(connectionProvider -> { connectionProviderMap.put(tenantIdentifier, connectionProvider); return connectionProvider; }) // - .orElseThrow(() -> new ConnectionProviderException( - String.format("Cannot create new connection provider for tenant: %s", tenantIdentifier))); + .orElseThrow(() -> new ConnectionProviderException(String + .format("Cannot create new connection provider for tenant: %s", tenantIdentifier))); } private ConnectionProvider createConnectionProvider(String tenantIdentifier) { - return Optional.ofNullable(tenantIdentifier) // + return Optional + .ofNullable(tenantIdentifier) // .map(this::getHibernatePropertiesForTenantIdentifier) // .map(this::initConnectionProvider) // .orElse(null); diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantConfigProvider.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantConfigProvider.java index 97521d9d7a..374ad302d3 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantConfigProvider.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantConfigProvider.java @@ -1,44 +1,62 @@ package ch.puzzle.okr.multitenancy; +import java.text.MessageFormat; +import java.util.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; -import java.text.MessageFormat; -import java.util.*; - @Component public class TenantConfigProvider implements TenantConfigProviderInterface { private static final String EMAIL_DELIMITER = ","; private final Map tenantConfigs = new HashMap<>(); private final Environment env; - public TenantConfigProvider(final @Value("${okr.tenant-ids}") String[] tenantIds, Environment env) { + public TenantConfigProvider(final @Value("${okr.tenant-ids}") + String[] tenantIds, Environment env) { this.env = env; for (String tenantId : tenantIds) { OauthConfig c = readOauthConfig(tenantId); - tenantConfigs.put(tenantId, - createTenantConfig(c.jwkSetUri(), c.frontendClientIssuerUrl(), c.frontendClientId(), tenantId)); + tenantConfigs + .put(tenantId, + createTenantConfig(c.jwkSetUri(), + c.frontendClientIssuerUrl(), + c.frontendClientId(), + tenantId)); } } private OauthConfig readOauthConfig(String tenantId) { - return new OauthConfig( - env.getProperty(MessageFormat.format("okr.tenants.{0}.security.oauth2.resourceserver.jwt.jwk-set-uri", - tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.security.oauth2.frontend.issuer-url", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.security.oauth2.frontend.client-id", tenantId))); + return new OauthConfig(env + .getProperty(MessageFormat + .format("okr.tenants.{0}.security.oauth2.resourceserver.jwt.jwk-set-uri", tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.security.oauth2.frontend.issuer-url", + tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.security.oauth2.frontend.client-id", + tenantId))); } private TenantConfig createTenantConfig(String jwkSetUriTemplate, String frontendClientIssuerUrl, - String frontendClientId, String tenantId) { - return new TenantConfig(tenantId, getOkrChampionEmailsFromTenant(tenantId), jwkSetUriTemplate, - frontendClientIssuerUrl, frontendClientId, this.readDataSourceConfig(tenantId)); + String frontendClientId, String tenantId) { + return new TenantConfig(tenantId, + getOkrChampionEmailsFromTenant(tenantId), + jwkSetUriTemplate, + frontendClientIssuerUrl, + frontendClientId, + this.readDataSourceConfig(tenantId)); } private String[] getOkrChampionEmailsFromTenant(String tenantId) { - return Arrays.stream(env.getProperty(MessageFormat.format("okr.tenants.{0}.user.champion.emails", tenantId), "") - .split(EMAIL_DELIMITER)).map(String::trim).toArray(String[]::new); + return Arrays + .stream(env + .getProperty(MessageFormat.format("okr.tenants.{0}.user.champion.emails", tenantId), "") + .split(EMAIL_DELIMITER)) + .map(String::trim) + .toArray(String[]::new); } public List getTenantConfigs() { @@ -47,10 +65,16 @@ public List getTenantConfigs() { private DataSourceConfig readDataSourceConfig(String tenantId) { return new DataSourceConfig(env.getProperty("okr.datasource.driver-class-name"), - env.getProperty(MessageFormat.format("okr.tenants.{0}.datasource.url", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.datasource.username", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.datasource.password", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.datasource.schema", tenantId))); + env.getProperty(MessageFormat.format("okr.tenants.{0}.datasource.url", tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.datasource.username", tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.datasource.password", tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.datasource.schema", tenantId))); } public Optional getTenantConfigById(String tenantId) { diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantContext.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantContext.java index 7c560ecf8c..d7e16756c9 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantContext.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/TenantContext.java @@ -1,10 +1,9 @@ package ch.puzzle.okr.multitenancy; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Optional; - public class TenantContext { public static final String DEFAULT_TENANT_ID = "public"; private static final Logger logger = LoggerFactory.getLogger(TenantContext.class); diff --git a/backend/src/main/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProvider.java b/backend/src/main/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProvider.java index 3749a7ec1f..b2886711d6 100644 --- a/backend/src/main/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProvider.java +++ b/backend/src/main/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProvider.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.multitenancy.customization; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; - import java.io.Serializable; import java.text.MessageFormat; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; @Component public class TenantClientCustomizationProvider { @@ -23,12 +22,18 @@ public class TenantClientCustomizationProvider { private static final String ADD_OBJECTIVE_OUTLINE_COLOR = ".okr-add-objective-outline-color"; private final Map tenantCustomizations = new HashMap<>(); - private final List customCssStyles = List.of(TOPBAR_BACKGROUND_COLOR, BANNER_BACKGROUND_COLOR, - OVERVIEW_BACKGROUND_COLOR, TEAM_HEADER_COLOR, ADD_OBJECTIVE_TEXT_COLOR, ADD_OBJECTIVE_ICON, - ADD_OBJECTIVE_OUTLINE_COLOR); + private final List customCssStyles = List + .of(TOPBAR_BACKGROUND_COLOR, + BANNER_BACKGROUND_COLOR, + OVERVIEW_BACKGROUND_COLOR, + TEAM_HEADER_COLOR, + ADD_OBJECTIVE_TEXT_COLOR, + ADD_OBJECTIVE_ICON, + ADD_OBJECTIVE_OUTLINE_COLOR); private final Environment env; - public TenantClientCustomizationProvider(final @Value("${okr.tenant-ids}") String[] tenantIds, Environment env) { + public TenantClientCustomizationProvider(final @Value("${okr.tenant-ids}") + String[] tenantIds, Environment env) { this.env = env; for (String tenantId : tenantIds) { readClientCustomizationConfig(tenantId); @@ -37,14 +42,29 @@ public TenantClientCustomizationProvider(final @Value("${okr.tenant-ids}") Strin } private TenantClientCustomization readClientCustomizationConfig(String tenantId) { - return new TenantClientCustomization( - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.favicon", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.logo", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.triangles", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.background-logo", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.title", tenantId)), - env.getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.helpSiteUrl", tenantId)), - getCustomCssStyles(tenantId) // + return new TenantClientCustomization(env + .getProperty(MessageFormat.format("okr.tenants.{0}.clientcustomization.favicon", tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.clientcustomization.logo", + tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.clientcustomization.triangles", + tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.clientcustomization.background-logo", + tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.clientcustomization.title", + tenantId)), + env + .getProperty(MessageFormat + .format("okr.tenants.{0}.clientcustomization.helpSiteUrl", + tenantId)), + getCustomCssStyles(tenantId) // ); } diff --git a/backend/src/main/java/ch/puzzle/okr/repository/ActionRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/ActionRepository.java index c6baa06bb4..ed82d16e41 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/ActionRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/ActionRepository.java @@ -1,9 +1,8 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.Action; -import org.springframework.data.repository.CrudRepository; - import java.util.List; +import org.springframework.data.repository.CrudRepository; public interface ActionRepository extends CrudRepository { List getActionsByKeyResultIdOrderByPriorityAsc(Long keyResultId); diff --git a/backend/src/main/java/ch/puzzle/okr/repository/AlignmentRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/AlignmentRepository.java index d6ebcc70a7..12ab5a8af3 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/AlignmentRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/AlignmentRepository.java @@ -3,12 +3,11 @@ import ch.puzzle.okr.models.alignment.Alignment; import ch.puzzle.okr.models.alignment.KeyResultAlignment; import ch.puzzle.okr.models.alignment.ObjectiveAlignment; +import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; -import java.util.List; - public interface AlignmentRepository extends CrudRepository { List findByAlignedObjectiveId(Long alignedObjectiveId); diff --git a/backend/src/main/java/ch/puzzle/okr/repository/AlignmentSelectionRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/AlignmentSelectionRepository.java index 50896b44f3..dcd03ab8bc 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/AlignmentSelectionRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/AlignmentSelectionRepository.java @@ -2,14 +2,13 @@ import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.models.alignment.AlignmentSelectionId; +import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import java.util.List; - public interface AlignmentSelectionRepository extends ReadOnlyRepository { @Query(value = "from AlignmentSelection where quarterId = :quarter_id and teamId != :ignoredTeamId") List getAlignmentSelectionByQuarterIdAndTeamIdNot(@Param("quarter_id") Long quarterId, - @Param("ignoredTeamId") Long ignoredTeamId); + @Param("ignoredTeamId") Long ignoredTeamId); } diff --git a/backend/src/main/java/ch/puzzle/okr/repository/CheckInRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/CheckInRepository.java index 74622032a2..3a17fecf0e 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/CheckInRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/CheckInRepository.java @@ -1,9 +1,8 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.checkin.CheckIn; -import org.springframework.data.repository.CrudRepository; - import java.util.List; +import org.springframework.data.repository.CrudRepository; public interface CheckInRepository extends CrudRepository { List findCheckInsByKeyResultIdOrderByCreatedOnDesc(Long keyResultId); diff --git a/backend/src/main/java/ch/puzzle/okr/repository/KeyResultRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/KeyResultRepository.java index b5aa92dbac..a48afe82e1 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/KeyResultRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/KeyResultRepository.java @@ -1,9 +1,8 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.keyresult.KeyResult; -import org.springframework.data.repository.CrudRepository; - import java.util.List; +import org.springframework.data.repository.CrudRepository; public interface KeyResultRepository extends CrudRepository { List findByObjectiveId(Long objectiveId); diff --git a/backend/src/main/java/ch/puzzle/okr/repository/ObjectiveRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/ObjectiveRepository.java index 009b34ac96..95f2fe0dbf 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/ObjectiveRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/ObjectiveRepository.java @@ -3,11 +3,10 @@ import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.models.Team; +import java.util.List; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface ObjectiveRepository extends CrudRepository { diff --git a/backend/src/main/java/ch/puzzle/okr/repository/QuarterRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/QuarterRepository.java index a742c2d236..a1089c7d09 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/QuarterRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/QuarterRepository.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.Quarter; +import java.time.LocalDate; +import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.time.LocalDate; -import java.util.List; - @Repository public interface QuarterRepository extends CrudRepository { diff --git a/backend/src/main/java/ch/puzzle/okr/repository/TeamRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/TeamRepository.java index 14e48978ed..f4aaf40bb9 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/TeamRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/TeamRepository.java @@ -1,9 +1,8 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.Team; -import org.springframework.data.repository.CrudRepository; - import java.util.List; +import org.springframework.data.repository.CrudRepository; public interface TeamRepository extends CrudRepository { diff --git a/backend/src/main/java/ch/puzzle/okr/repository/UserRepository.java b/backend/src/main/java/ch/puzzle/okr/repository/UserRepository.java index 2bf83e1f1d..addae09197 100644 --- a/backend/src/main/java/ch/puzzle/okr/repository/UserRepository.java +++ b/backend/src/main/java/ch/puzzle/okr/repository/UserRepository.java @@ -1,10 +1,9 @@ package ch.puzzle.okr.repository; import ch.puzzle.okr.models.User; -import org.springframework.data.repository.CrudRepository; - import java.util.List; import java.util.Optional; +import org.springframework.data.repository.CrudRepository; public interface UserRepository extends CrudRepository { Optional findByEmail(String email); diff --git a/backend/src/main/java/ch/puzzle/okr/security/JwtHelper.java b/backend/src/main/java/ch/puzzle/okr/security/JwtHelper.java index fe15d284f1..6e2034416e 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/JwtHelper.java +++ b/backend/src/main/java/ch/puzzle/okr/security/JwtHelper.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.security; +import static ch.puzzle.okr.Constants.USER; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; @@ -8,28 +11,24 @@ import ch.puzzle.okr.security.helper.TokenHelper; import com.nimbusds.jwt.JWTClaimsSet; import jakarta.persistence.EntityNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.stereotype.Component; - import java.text.MessageFormat; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Function; - -import static ch.puzzle.okr.Constants.USER; -import static org.springframework.http.HttpStatus.BAD_REQUEST; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.stereotype.Component; @Component public class JwtHelper { public static final String CLAIM_TENANT = "tenant"; public static final String CLAIM_ISS = "iss"; public static final String ERROR_MESSAGE = "Missing `" + CLAIM_TENANT + "` and '" + CLAIM_ISS - + "' claims in JWT token!"; + + "' claims in JWT token!"; private static final Logger logger = LoggerFactory.getLogger(JwtHelper.class); @@ -39,9 +38,9 @@ public class JwtHelper { private final String email; public JwtHelper(TenantConfigProvider tenantConfigProvider, - @Value("${okr.jwt.claim.firstname}") final String tokenClaimsKeyFirstname, - @Value("${okr.jwt.claim.lastname}") final String tokenClaimsKeyLastname, - @Value("${okr.jwt.claim.email}") final String tokenClaimsKeyEmail) { + @Value("${okr.jwt.claim.firstname}") final String tokenClaimsKeyFirstname, + @Value("${okr.jwt.claim.lastname}") final String tokenClaimsKeyLastname, + @Value("${okr.jwt.claim.email}") final String tokenClaimsKeyEmail) { this.tenantConfigProvider = tenantConfigProvider; this.firstname = tokenClaimsKeyFirstname; this.lastname = tokenClaimsKeyLastname; @@ -53,7 +52,8 @@ public User getUserFromJwt(Jwt token) { logger.debug("claims {}", claims); try { - return User.Builder.builder() // + return User.Builder + .builder() // .withFirstname(claims.get(firstname).toString()) // .withLastname(claims.get(lastname).toString()) // .withEmail(claims.get(email).toString()) // @@ -66,18 +66,20 @@ public User getUserFromJwt(Jwt token) { public String getTenantFromToken(Jwt token) { TokenHelper helper = new TokenHelper(); - List>> getTenantFromTokenFunctions = Arrays.asList( // - helper::getTenantFromTokenUsingClaimIss, // - helper::getTenantFromTokenUsingClaimTenant // - ); + List>> getTenantFromTokenFunctions = Arrays + .asList( // + helper::getTenantFromTokenUsingClaimIss, // + helper::getTenantFromTokenUsingClaimTenant // + ); return getFirstMatchingTenantUsingListOfHelperFunctions(token, getTenantFromTokenFunctions); } private String getFirstMatchingTenantUsingListOfHelperFunctions(Jwt token, - List>> getTenantFunctions) { + List>> getTenantFunctions) { - return getTenantFunctions.stream() // + return getTenantFunctions + .stream() // .map(func -> func.apply(token)) // .filter(Optional::isPresent) // .map(Optional::get) // @@ -88,28 +90,32 @@ private String getFirstMatchingTenantUsingListOfHelperFunctions(Jwt token, public String getTenantFromJWTClaimsSet(JWTClaimsSet claimSet) { ClaimHelper helper = new ClaimHelper(); - List>> getTenantFromClaimsSetFunctions = Arrays.asList( // - helper::getTenantFromClaimsSetUsingClaimIss, // - helper::getTenantFromClaimsSetUsingClaimTenant // - ); + List>> getTenantFromClaimsSetFunctions = Arrays + .asList( // + helper::getTenantFromClaimsSetUsingClaimIss, // + helper::getTenantFromClaimsSetUsingClaimTenant // + ); return getFirstMatchingTenantUsingListOfHelperFunctions(claimSet, getTenantFromClaimsSetFunctions); } private String getFirstMatchingTenantUsingListOfHelperFunctions(JWTClaimsSet claimSet, - List>> getTenantFunctions) { + List>> getTenantFunctions) { - return getTenantFunctions.stream() // + return getTenantFunctions + .stream() // .map(func -> func.apply(claimSet)) // .filter(Optional::isPresent) // .map(Optional::get) // - .map(this::getMatchingTenantFromConfigOrThrow).findFirst() // + .map(this::getMatchingTenantFromConfigOrThrow) + .findFirst() // .orElseThrow(() -> new RuntimeException(ERROR_MESSAGE)); } private String getMatchingTenantFromConfigOrThrow(String tenant) { // Ensure we return only tenants for realms which really exist - return this.tenantConfigProvider.getTenantConfigById(tenant) + return this.tenantConfigProvider + .getTenantConfigById(tenant) .orElseThrow(() -> new EntityNotFoundException(MessageFormat.format("Cannot find tenant {0}", tenant))) .tenantId(); } diff --git a/backend/src/main/java/ch/puzzle/okr/security/TenantJWSKeySelector.java b/backend/src/main/java/ch/puzzle/okr/security/TenantJWSKeySelector.java index f900296174..0df2cbc8a2 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/TenantJWSKeySelector.java +++ b/backend/src/main/java/ch/puzzle/okr/security/TenantJWSKeySelector.java @@ -8,13 +8,12 @@ import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.proc.JWTClaimsSetAwareJWSKeySelector; -import org.springframework.stereotype.Component; - import java.net.URL; import java.security.Key; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.springframework.stereotype.Component; @Component public class TenantJWSKeySelector implements JWTClaimsSetAwareJWSKeySelector { @@ -31,9 +30,11 @@ public TenantJWSKeySelector(final TenantConfigProvider tenantConfigProvider, Jwt @Override public List selectKeys(JWSHeader jwsHeader, JWTClaimsSet jwtClaimsSet, - SecurityContext securityContext) throws KeySourceException { + SecurityContext securityContext) + throws KeySourceException { - return this.selectors.computeIfAbsent(toTenant(jwtClaimsSet), this::fromTenant) // + return this.selectors + .computeIfAbsent(toTenant(jwtClaimsSet), this::fromTenant) // .selectJWSKeys(jwsHeader, securityContext); } @@ -42,7 +43,8 @@ private String toTenant(JWTClaimsSet claimSet) { } private JWSKeySelector fromTenant(String tenantId) { - return this.tenantConfigProvider.getJwkSetUri(tenantId)// + return this.tenantConfigProvider + .getJwkSetUri(tenantId)// .map(this::fromUri) // .orElseThrow(() -> new IllegalArgumentException("unknown tenant")); } diff --git a/backend/src/main/java/ch/puzzle/okr/security/TenantJwtIssuerValidator.java b/backend/src/main/java/ch/puzzle/okr/security/TenantJwtIssuerValidator.java index 1dadd96b3f..4f84b487bc 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/TenantJwtIssuerValidator.java +++ b/backend/src/main/java/ch/puzzle/okr/security/TenantJwtIssuerValidator.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.security; import ch.puzzle.okr.multitenancy.TenantConfigProvider; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtIssuerValidator; import org.springframework.stereotype.Component; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - @Component public class TenantJwtIssuerValidator implements OAuth2TokenValidator { private final TenantConfigProvider tenantConfigProvider; @@ -31,7 +30,8 @@ public OAuth2TokenValidatorResult validate(Jwt token) { } private JwtIssuerValidator createValidatorForTenant(String tenant) { - return this.tenantConfigProvider.getTenantConfigById(tenant) // + return this.tenantConfigProvider + .getTenantConfigById(tenant) // .map(TenantConfigProvider.TenantConfig::issuerUrl) // .map(this::createValidator) // .orElseThrow(() -> new IllegalArgumentException("unknown tenant")); diff --git a/backend/src/main/java/ch/puzzle/okr/security/helper/ClaimHelper.java b/backend/src/main/java/ch/puzzle/okr/security/helper/ClaimHelper.java index 9ceb7a4034..b7fb0b88de 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/helper/ClaimHelper.java +++ b/backend/src/main/java/ch/puzzle/okr/security/helper/ClaimHelper.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.security.helper; -import com.nimbusds.jwt.JWTClaimsSet; - -import java.text.ParseException; -import java.util.Optional; - import static ch.puzzle.okr.security.JwtHelper.CLAIM_ISS; import static ch.puzzle.okr.security.JwtHelper.CLAIM_TENANT; import static ch.puzzle.okr.security.helper.JwtStatusLogger.logStatus; import static ch.puzzle.okr.security.helper.UrlHelper.extractTenantFromIssUrl; +import com.nimbusds.jwt.JWTClaimsSet; +import java.text.ParseException; +import java.util.Optional; + public class ClaimHelper { public Optional getTenantFromClaimsSetUsingClaimTenant(JWTClaimsSet claimSet) { diff --git a/backend/src/main/java/ch/puzzle/okr/security/helper/JwtStatusLogger.java b/backend/src/main/java/ch/puzzle/okr/security/helper/JwtStatusLogger.java index ca5d678458..364f77dc83 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/helper/JwtStatusLogger.java +++ b/backend/src/main/java/ch/puzzle/okr/security/helper/JwtStatusLogger.java @@ -1,10 +1,9 @@ package ch.puzzle.okr.security.helper; +import java.text.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.ParseException; - public class JwtStatusLogger { private static final Logger logger = LoggerFactory.getLogger(ClaimHelper.class); @@ -15,17 +14,27 @@ public static void logStatus(String claim, Object context, String result) { public static void logStatus(String claim, Object context, boolean isOk) { if (isOk) { - logger.info("Tenant: get claim '{}' from {}{}", claim, context.getClass().getSimpleName(), - statusToSymbol(isOk)); + logger + .info("Tenant: get claim '{}' from {}{}", + claim, + context.getClass().getSimpleName(), + statusToSymbol(isOk)); } else { - logger.warn("Tenant: get claim '{}' from {}{}", claim, context.getClass().getSimpleName(), - statusToSymbol(isOk)); + logger + .warn("Tenant: get claim '{}' from {}{}", + claim, + context.getClass().getSimpleName(), + statusToSymbol(isOk)); } } public static void logStatus(String claim, Object context, ParseException e) { - logger.warn("Tenant: get claim '{}' from {}{}", claim, context.getClass().getSimpleName(), - statusToSymbol(false), e); + logger + .warn("Tenant: get claim '{}' from {}{}", + claim, + context.getClass().getSimpleName(), + statusToSymbol(false), + e); } private static String statusToSymbol(boolean isOk) { diff --git a/backend/src/main/java/ch/puzzle/okr/security/helper/TokenHelper.java b/backend/src/main/java/ch/puzzle/okr/security/helper/TokenHelper.java index 513241cb06..8bdab64f86 100644 --- a/backend/src/main/java/ch/puzzle/okr/security/helper/TokenHelper.java +++ b/backend/src/main/java/ch/puzzle/okr/security/helper/TokenHelper.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.security.helper; -import org.springframework.security.oauth2.jwt.Jwt; - -import java.util.Optional; - import static ch.puzzle.okr.security.JwtHelper.CLAIM_ISS; import static ch.puzzle.okr.security.JwtHelper.CLAIM_TENANT; import static ch.puzzle.okr.security.helper.JwtStatusLogger.logStatus; import static ch.puzzle.okr.security.helper.UrlHelper.extractTenantFromIssUrl; +import java.util.Optional; +import org.springframework.security.oauth2.jwt.Jwt; + public class TokenHelper { public Optional getTenantFromTokenUsingClaimTenant(Jwt token) { diff --git a/backend/src/main/java/ch/puzzle/okr/service/CacheService.java b/backend/src/main/java/ch/puzzle/okr/service/CacheService.java index de907468c1..5a315116fd 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/CacheService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/CacheService.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.service; +import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; @@ -8,8 +10,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; - @EnableScheduling @Service public class CacheService { diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/ActionAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/ActionAuthorizationService.java index a6a54a4de4..937e5a893b 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/ActionAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/ActionAuthorizationService.java @@ -4,9 +4,8 @@ import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.business.ActionBusinessService; -import org.springframework.stereotype.Service; - import java.util.List; +import org.springframework.stereotype.Service; @Service public class ActionAuthorizationService { @@ -15,7 +14,7 @@ public class ActionAuthorizationService { private final AuthorizationService authorizationService; public ActionAuthorizationService(ActionBusinessService actionBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { this.actionBusinessService = actionBusinessService; this.authorizationService = authorizationService; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationService.java index fc1213b565..33980f8fad 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationService.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.multitenancy.TenantConfigProvider; @@ -9,8 +11,6 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; - @Service public class AuthorizationRegistrationService { @@ -20,7 +20,7 @@ public class AuthorizationRegistrationService { private final UserUpdateHelper helper = new UserUpdateHelper(); public AuthorizationRegistrationService(UserBusinessService userBusinessService, - TenantConfigProvider tenantConfigProvider) { + TenantConfigProvider tenantConfigProvider) { this.userBusinessService = userBusinessService; this.tenantConfigProvider = tenantConfigProvider; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationService.java index 3ddde9734b..b249332663 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationService.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.Constants.*; +import static ch.puzzle.okr.ErrorKey.*; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.Objective; @@ -17,9 +20,6 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.stereotype.Service; -import static ch.puzzle.okr.Constants.*; -import static ch.puzzle.okr.ErrorKey.*; - @Service public class AuthorizationService { @@ -29,8 +29,8 @@ public class AuthorizationService { private final JwtHelper jwtHelper; public AuthorizationService(AuthorizationRegistrationService authorizationRegistrationService, - ObjectivePersistenceService objectivePersistenceService, ActionPersistenceService actionPersistenceService, - JwtHelper jwtHelper) { + ObjectivePersistenceService objectivePersistenceService, + ActionPersistenceService actionPersistenceService, JwtHelper jwtHelper) { this.authorizationRegistrationService = authorizationRegistrationService; this.actionPersistenceService = actionPersistenceService; this.objectivePersistenceService = objectivePersistenceService; @@ -45,7 +45,7 @@ public static boolean hasRoleWriteForTeam(AuthorizationUser authorizationUser, L } public static void checkRoleWriteAndReadAll(AuthorizationUser user, - OkrResponseStatusException notAuthorizedException) { + OkrResponseStatusException notAuthorizedException) { if (hasRoleWriteAndReadAll(user)) { return; } @@ -67,40 +67,53 @@ public AuthorizationUser updateOrAddAuthorizationUser() { } public void hasRoleReadByObjectiveId(Long objectiveId, AuthorizationUser authorizationUser) { - objectivePersistenceService.findObjectiveById(objectiveId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); + objectivePersistenceService + .findObjectiveById(objectiveId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); } public void hasRoleReadByKeyResultId(Long keyResultId, AuthorizationUser authorizationUser) { - objectivePersistenceService.findObjectiveByKeyResultId(keyResultId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); + objectivePersistenceService + .findObjectiveByKeyResultId(keyResultId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); } public void hasRoleReadByCheckInId(Long checkInId, AuthorizationUser authorizationUser) { - objectivePersistenceService.findObjectiveByCheckInId(checkInId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); + objectivePersistenceService + .findObjectiveByCheckInId(checkInId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); } public void hasRoleCreateOrUpdate(Objective objective, AuthorizationUser authorizationUser) { - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, OBJECTIVE)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, OBJECTIVE)); } public void hasRoleCreateOrUpdate(KeyResult keyResult, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveById(keyResult.getObjective().getId(), - authorizationUser, OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); + Objective objective = objectivePersistenceService + .findObjectiveById(keyResult.getObjective().getId(), + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, KEY_RESULT)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, KEY_RESULT)); } public void hasRoleCreateOrUpdate(CheckIn checkIn, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveByKeyResultId(checkIn.getKeyResult().getId(), - authorizationUser, OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); + Objective objective = objectivePersistenceService + .findObjectiveByKeyResultId(checkIn.getKeyResult().getId(), + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, CHECK_IN)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, CHECK_IN)); } public boolean hasRoleWriteForTeam(Objective objective, AuthorizationUser authorizationUser) { @@ -108,59 +121,76 @@ public boolean hasRoleWriteForTeam(Objective objective, AuthorizationUser author } public boolean hasRoleWriteForTeam(KeyResult keyResult, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveById(keyResult.getObjective().getId(), - authorizationUser, OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); + Objective objective = objectivePersistenceService + .findObjectiveById(keyResult.getObjective().getId(), + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); return hasRoleWriteForTeam(authorizationUser, objective.getTeam()); } public boolean hasRoleWriteForTeam(CheckIn checkIn, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveByKeyResultId(checkIn.getKeyResult().getId(), - authorizationUser, OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); + Objective objective = objectivePersistenceService + .findObjectiveByKeyResultId(checkIn.getKeyResult().getId(), + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); return hasRoleWriteForTeam(authorizationUser, objective.getTeam()); } public void hasRoleCreateOrUpdateByObjectiveId(Long objectiveId, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveById(objectiveId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); + Objective objective = objectivePersistenceService + .findObjectiveById(objectiveId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, OBJECTIVE)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_WRITE, OBJECTIVE)); } public void hasRoleDeleteByObjectiveId(Long objectiveId, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveById(objectiveId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); + Objective objective = objectivePersistenceService + .findObjectiveById(objectiveId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, OBJECTIVE)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, OBJECTIVE)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, OBJECTIVE)); } public void hasRoleDeleteByKeyResultId(Long keyResultId, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveByKeyResultId(keyResultId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); + Objective objective = objectivePersistenceService + .findObjectiveByKeyResultId(keyResultId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, KEY_RESULT)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, KEY_RESULT)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, KEY_RESULT)); } public void hasRoleDeleteByActionId(Long actionId, AuthorizationUser authorizationUser) { Action action = actionPersistenceService.findById(actionId); - hasRoleWriteForTeam(authorizationUser, action.getKeyResult().getObjective().getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, ACTION)); + hasRoleWriteForTeam(authorizationUser, + action.getKeyResult().getObjective().getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, ACTION)); } public void hasRoleDeleteByCheckInId(Long checkInId, AuthorizationUser authorizationUser) { - Objective objective = objectivePersistenceService.findObjectiveByCheckInId(checkInId, authorizationUser, - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); + Objective objective = objectivePersistenceService + .findObjectiveByCheckInId(checkInId, + authorizationUser, + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, CHECK_IN)); - hasRoleWriteForTeam(authorizationUser, objective.getTeam(), - OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, CHECK_IN)); + hasRoleWriteForTeam(authorizationUser, + objective.getTeam(), + OkrResponseStatusException.of(NOT_AUTHORIZED_TO_DELETE, CHECK_IN)); } private void hasRoleWriteForTeam(AuthorizationUser authorizationUser, Team team, - OkrResponseStatusException notAuthorizedException) { + OkrResponseStatusException notAuthorizedException) { if (hasRoleWriteForTeam(authorizationUser, team)) { return; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationServiceBase.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationServiceBase.java index 51cd7ab046..92766a80fc 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationServiceBase.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/AuthorizationServiceBase.java @@ -17,7 +17,7 @@ public abstract class AuthorizationServiceBase businessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { this.businessService = businessService; this.authorizationService = authorizationService; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationService.java index bb6196d6f6..04c8f6f64e 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationService.java @@ -9,7 +9,7 @@ public class CheckInAuthorizationService extends AuthorizationServiceBase { public CheckInAuthorizationService(CheckInBusinessService checkInBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { super(checkInBusinessService, authorizationService); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationService.java index a59467a3ca..3ea9524532 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationService.java @@ -11,7 +11,7 @@ public class CompletedAuthorizationService { private final AuthorizationService authorizationService; public CompletedAuthorizationService(CompletedBusinessService completedBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { this.completedBusinessService = completedBusinessService; this.authorizationService = authorizationService; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationService.java index a2197e89b5..a280f33bef 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationService.java @@ -1,23 +1,22 @@ package ch.puzzle.okr.service.authorization; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultWithActionList; import ch.puzzle.okr.service.business.KeyResultBusinessService; +import java.util.List; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @Service public class KeyResultAuthorizationService extends AuthorizationServiceBase { public KeyResultAuthorizationService(KeyResultBusinessService keyResultBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { super(keyResultBusinessService, authorizationService); } @@ -52,7 +51,8 @@ public List getAllCheckInsByKeyResult(Long keyResultId) { @Override public KeyResult updateEntity(Long id, KeyResult keyResult) { throw new ResponseStatusException(BAD_REQUEST, - "unsupported method in class " + getClass().getSimpleName() + ", use updateEntities() instead"); + "unsupported method in class " + getClass().getSimpleName() + + ", use updateEntities() instead"); } public KeyResultWithActionList updateEntities(Long id, KeyResult entity, List actionList) { diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationService.java index c98338d477..97d8fbb38b 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationService.java @@ -4,16 +4,14 @@ import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.business.ObjectiveBusinessService; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - import java.util.List; +import org.springframework.stereotype.Service; @Service public class ObjectiveAuthorizationService extends AuthorizationServiceBase { public ObjectiveAuthorizationService(ObjectiveBusinessService objectiveBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { super(objectiveBusinessService, authorizationService); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationService.java index 3f4487b31b..76f9a9f1df 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationService.java @@ -1,16 +1,15 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.service.business.OverviewBusinessService; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - import java.util.HashMap; import java.util.List; import java.util.Map; - -import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; @Service public class OverviewAuthorizationService { @@ -19,15 +18,15 @@ public class OverviewAuthorizationService { private final AuthorizationService authorizationService; public OverviewAuthorizationService(OverviewBusinessService overviewBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { this.overviewBusinessService = overviewBusinessService; this.authorizationService = authorizationService; } public List getFilteredOverview(Long quarterId, List teamIds, String objectiveQuery) { AuthorizationUser authorizationUser = authorizationService.updateOrAddAuthorizationUser(); - List overviews = overviewBusinessService.getFilteredOverview(quarterId, teamIds, objectiveQuery, - authorizationUser); + List overviews = overviewBusinessService + .getFilteredOverview(quarterId, teamIds, objectiveQuery, authorizationUser); setRoleCreateOrUpdateTeam(overviews, authorizationUser); return overviews; } @@ -40,7 +39,7 @@ private void setRoleCreateOrUpdateTeam(List overviews, AuthorizationUs } private void setRoleCreateOrUpdateTeam(Overview overview, AuthorizationUser authorizationUser, - Map teamAccess) { + Map teamAccess) { if (hasOverviewTeamIdAndObjectiveId(overview)) { Long teamId = overview.getOverviewId().getTeamId(); teamAccess.putIfAbsent(teamId, isWriteable(authorizationUser, overview)); @@ -50,7 +49,7 @@ private void setRoleCreateOrUpdateTeam(Overview overview, AuthorizationUser auth private boolean hasOverviewTeamIdAndObjectiveId(Overview overview) { return overview.getOverviewId() != null && overview.getOverviewId().getObjectiveId() != null - && overview.getOverviewId().getTeamId() != null; + && overview.getOverviewId().getTeamId() != null; } public boolean hasWriteAllAccess() { diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/TeamAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/TeamAuthorizationService.java index 33e2cecd33..0909821d35 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/TeamAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/TeamAuthorizationService.java @@ -1,16 +1,15 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.Constants.TEAM; +import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.service.business.TeamBusinessService; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.TEAM; -import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; +import org.springframework.stereotype.Service; @Service public class TeamAuthorizationService { @@ -18,7 +17,7 @@ public class TeamAuthorizationService { private final AuthorizationService authorizationService; public TeamAuthorizationService(TeamBusinessService teamBusinessService, - AuthorizationService authorizationService) { + AuthorizationService authorizationService) { this.teamBusinessService = teamBusinessService; this.authorizationService = authorizationService; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java index fab3dba8fe..9ec8444c6e 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.Constants.USER; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.dto.userOkrData.UserOkrDataDto; import ch.puzzle.okr.exception.OkrResponseStatusException; @@ -9,11 +11,8 @@ import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.business.KeyResultBusinessService; import ch.puzzle.okr.service.business.UserBusinessService; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.USER; +import org.springframework.stereotype.Service; @Service public class UserAuthorizationService { @@ -24,7 +23,8 @@ public class UserAuthorizationService { private final KeyResultBusinessService keyResultBusinessService; public UserAuthorizationService(UserBusinessService userBusinessService, AuthorizationService authorizationService, - TeamAuthorizationService teamAuthorizationService, KeyResultBusinessService keyResultBusinessService) { + TeamAuthorizationService teamAuthorizationService, + KeyResultBusinessService keyResultBusinessService) { this.userBusinessService = userBusinessService; this.authorizationService = authorizationService; this.teamAuthorizationService = teamAuthorizationService; @@ -54,14 +54,16 @@ public User getById(long id) { public User setIsOkrChampion(long id, boolean isOkrChampion) { var user = userBusinessService.getUserById(id); - AuthorizationService.checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), - OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER)); + AuthorizationService + .checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), + OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER)); return userBusinessService.setIsOkrChampion(user, isOkrChampion); } public List createUsers(List userList) { - AuthorizationService.checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), - OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER)); + AuthorizationService + .checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), + OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER)); return userBusinessService.createUsers(userList); } @@ -71,8 +73,9 @@ public boolean isUserMemberOfTeams(long id) { } public void deleteEntityById(long id) { - AuthorizationService.checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), - OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_DELETE, USER)); + AuthorizationService + .checkRoleWriteAndReadAll(authorizationService.updateOrAddAuthorizationUser(), + OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_DELETE, USER)); userBusinessService.deleteEntityById(id); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/ActionBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/ActionBusinessService.java index 9a684f6a54..7d1d1a9188 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/ActionBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/ActionBusinessService.java @@ -4,10 +4,9 @@ import ch.puzzle.okr.service.persistence.ActionPersistenceService; import ch.puzzle.okr.service.validation.ActionValidationService; import jakarta.transaction.Transactional; -import org.springframework.stereotype.Service; - import java.util.ArrayList; import java.util.List; +import org.springframework.stereotype.Service; @Service public class ActionBusinessService { diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentBusinessService.java index ea7d9644a9..4c4261fcf6 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentBusinessService.java @@ -5,9 +5,8 @@ import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.persistence.AlignmentPersistenceService; import ch.puzzle.okr.service.validation.AlignmentValidationService; -import org.springframework.stereotype.Service; - import java.util.List; +import org.springframework.stereotype.Service; @Service public class AlignmentBusinessService { @@ -15,7 +14,7 @@ public class AlignmentBusinessService { private final AlignmentValidationService validation; public AlignmentBusinessService(AlignmentPersistenceService alignmentPersistenceService, - AlignmentValidationService validation) { + AlignmentValidationService validation) { this.alignmentPersistenceService = alignmentPersistenceService; this.validation = validation; } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessService.java index 8e6feefed1..893a075c76 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessService.java @@ -2,22 +2,20 @@ import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.service.persistence.AlignmentSelectionPersistenceService; -import org.springframework.stereotype.Service; - import java.util.List; +import org.springframework.stereotype.Service; @Service public class AlignmentSelectionBusinessService { private final AlignmentSelectionPersistenceService alignmentSelectionPersistenceService; - public AlignmentSelectionBusinessService( - AlignmentSelectionPersistenceService alignmentSelectionPersistenceService) { + public AlignmentSelectionBusinessService(AlignmentSelectionPersistenceService alignmentSelectionPersistenceService) { this.alignmentSelectionPersistenceService = alignmentSelectionPersistenceService; } public List getAlignmentSelectionByQuarterIdAndTeamIdNot(Long quarterId, Long ignoredTeamId) { - return alignmentSelectionPersistenceService.getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterId, - ignoredTeamId); + return alignmentSelectionPersistenceService + .getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterId, ignoredTeamId); } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/CheckInBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/CheckInBusinessService.java index db6e892cb0..ad9456d175 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/CheckInBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/CheckInBusinessService.java @@ -5,10 +5,9 @@ import ch.puzzle.okr.service.persistence.CheckInPersistenceService; import ch.puzzle.okr.service.validation.CheckInValidationService; import jakarta.transaction.Transactional; -import org.springframework.stereotype.Service; - import java.time.LocalDateTime; import java.util.List; +import org.springframework.stereotype.Service; @Service public class CheckInBusinessService implements BusinessServiceInterface { @@ -16,7 +15,7 @@ public class CheckInBusinessService implements BusinessServiceInterface { @@ -28,8 +26,9 @@ public class KeyResultBusinessService implements BusinessServiceInterface acti @Transactional public void deleteEntityById(Long id) { validator.validateOnDelete(id); - checkInBusinessService.getCheckInsByKeyResultId(id) + checkInBusinessService + .getCheckInsByKeyResultId(id) .forEach(checkIn -> checkInBusinessService.deleteEntityById(checkIn.getId())); - actionBusinessService.getActionsByKeyResultId(id) + actionBusinessService + .getActionsByKeyResultId(id) .forEach(action -> actionBusinessService.deleteEntityById(action.getId())); keyResultPersistenceService.deleteById(id); } @@ -126,7 +127,7 @@ public boolean hasKeyResultAnyCheckIns(Long id) { public boolean isImUsed(Long id, KeyResult keyResult) { return hasKeyResultAnyCheckIns(id) - && !keyResultPersistenceService.findById(id).getKeyResultType().equals(keyResult.getKeyResultType()); + && !keyResultPersistenceService.findById(id).getKeyResultType().equals(keyResult.getKeyResultType()); } private boolean isKeyResultTypeChangeable(Long id) { diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/ObjectiveBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/ObjectiveBusinessService.java index 40f7eefd80..05f217180c 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/ObjectiveBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/ObjectiveBusinessService.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; + import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; @@ -8,18 +11,14 @@ import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.service.validation.ObjectiveValidationService; import jakarta.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; - @Service public class ObjectiveBusinessService implements BusinessServiceInterface { private static final Logger logger = LoggerFactory.getLogger(ObjectiveBusinessService.class); @@ -29,8 +28,9 @@ public class ObjectiveBusinessService implements BusinessServiceInterface keyResultBusinessService.hasKeyResultAnyCheckIns(kr.getId())); } @@ -105,8 +107,8 @@ public Objective createEntity(Objective objective, AuthorizationUser authorizati } /** - * Create a new Objective (with a new ID) and copy from a source Objective (identified by id) the KeyResults. The - * CheckIns are not copied. + * Create a new Objective (with a new ID) and copy from a source Objective + * (identified by id) the KeyResults. The CheckIns are not copied. * * @param id * ID of the source Objective @@ -121,7 +123,7 @@ public Objective createEntity(Objective objective, AuthorizationUser authorizati */ @Transactional public Objective duplicateObjective(Long id, Objective objective, AuthorizationUser authorizationUser, - List keyResults) { + List keyResults) { Objective duplicatedObjective = createEntity(objective, authorizationUser); for (KeyResult keyResult : keyResults) { duplicateKeyResult(authorizationUser, keyResult, duplicatedObjective); @@ -130,7 +132,7 @@ public Objective duplicateObjective(Long id, Objective objective, AuthorizationU } private void duplicateKeyResult(AuthorizationUser authorizationUser, KeyResult keyResult, - Objective duplicatedObjective) { + Objective duplicatedObjective) { if (keyResult.getKeyResultType().equals(KEY_RESULT_TYPE_METRIC)) { KeyResult keyResultMetric = makeCopyOfKeyResultMetric(keyResult, duplicatedObjective); keyResultBusinessService.createEntity(keyResultMetric, authorizationUser); @@ -141,7 +143,8 @@ private void duplicateKeyResult(AuthorizationUser authorizationUser, KeyResult k } private KeyResult makeCopyOfKeyResultMetric(KeyResult keyResult, Objective duplicatedObjective) { - return KeyResultMetric.Builder.builder() // + return KeyResultMetric.Builder + .builder() // .withObjective(duplicatedObjective) // .withTitle(keyResult.getTitle()) // .withDescription(keyResult.getDescription()) // @@ -153,7 +156,8 @@ private KeyResult makeCopyOfKeyResultMetric(KeyResult keyResult, Objective dupli } private KeyResult makeCopyOfKeyResultOrdinal(KeyResult keyResult, Objective duplicatedObjective) { - return KeyResultOrdinal.Builder.builder() // + return KeyResultOrdinal.Builder + .builder() // .withObjective(duplicatedObjective) // .withTitle(keyResult.getTitle()) // .withDescription(keyResult.getDescription()) // diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/OverviewBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/OverviewBusinessService.java index da721f6c27..677d6a626a 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/OverviewBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/OverviewBusinessService.java @@ -4,11 +4,10 @@ import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.service.persistence.OverviewPersistenceService; import ch.puzzle.okr.service.validation.OverviewValidationService; -import org.springframework.stereotype.Service; - import java.util.Comparator; import java.util.List; import java.util.Objects; +import org.springframework.stereotype.Service; @Service public class OverviewBusinessService { @@ -17,14 +16,14 @@ public class OverviewBusinessService { private final OverviewValidationService validator; public OverviewBusinessService(OverviewPersistenceService overviewPersistenceService, - QuarterBusinessService quarterBusinessService, OverviewValidationService validator) { + QuarterBusinessService quarterBusinessService, OverviewValidationService validator) { this.overviewPersistenceService = overviewPersistenceService; this.quarterBusinessService = quarterBusinessService; this.validator = validator; } public List getFilteredOverview(Long quarterId, List teamIds, String objectiveQuery, - AuthorizationUser authorizationUser) { + AuthorizationUser authorizationUser) { if (Objects.isNull(quarterId)) { quarterId = quarterBusinessService.getCurrentQuarter().getId(); } @@ -35,8 +34,8 @@ public List getFilteredOverview(Long quarterId, List teamIds, St return List.of(); } - List overviews = overviewPersistenceService.getFilteredOverview(quarterId, teamIds, objectiveQuery, - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(quarterId, teamIds, objectiveQuery, authorizationUser); return sortOverview(overviews, authorizationUser); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/QuarterBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/QuarterBusinessService.java index 5f6c35053b..7069eb4cf9 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/QuarterBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/QuarterBusinessService.java @@ -1,8 +1,15 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.service.persistence.QuarterPersistenceService; import ch.puzzle.okr.service.validation.QuarterValidationService; +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,14 +17,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import java.time.LocalDateTime; -import java.time.YearMonth; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; - @Service public class QuarterBusinessService { private static final Logger logger = LoggerFactory.getLogger(QuarterBusinessService.class); @@ -32,7 +31,7 @@ public class QuarterBusinessService { private String quarterFormat; public QuarterBusinessService(QuarterPersistenceService quarterPersistenceService, - QuarterValidationService validator) { + QuarterValidationService validator) { this.quarterPersistenceService = quarterPersistenceService; this.validator = validator; } @@ -66,9 +65,11 @@ private String createQuarterLabel(YearMonth startOfQuarter, int quarter) { int yearStart = getStartOfBusinessYear(startOfQuarter, quarter); int yearEnd = yearStart + 1; - return StringUtils.replaceEach(quarterFormat, new String[] { "xxxx", "yyyy", "xx", "yy", "zz" }, - new String[] { String.valueOf(yearStart), String.valueOf(yearEnd), shortenYear(yearStart), - shortenYear(yearEnd), String.valueOf(quarter) }); + return StringUtils + .replaceEach(quarterFormat, + new String[]{ "xxxx", "yyyy", "xx", "yy", "zz" }, + new String[]{ String.valueOf(yearStart), String.valueOf(yearEnd), shortenYear(yearStart), + shortenYear(yearEnd), String.valueOf(quarter) }); } private int getStartOfBusinessYear(YearMonth startOfQuarter, int quarter) { @@ -79,8 +80,12 @@ private int getStartOfBusinessYear(YearMonth startOfQuarter, int quarter) { private void generateQuarter(LocalDateTime start, String label) { YearMonth yearMonth = YearMonth.from(start); - Quarter quarter = Quarter.Builder.builder().withLabel(label).withStartDate(start.toLocalDate()) - .withEndDate(yearMonth.plusMonths(2).atEndOfMonth()).build(); + Quarter quarter = Quarter.Builder + .builder() + .withLabel(label) + .withStartDate(start.toLocalDate()) + .withEndDate(yearMonth.plusMonths(2).atEndOfMonth()) + .build(); validator.validateOnGeneration(quarter); quarterPersistenceService.save(quarter); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/TeamBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/TeamBusinessService.java index f05a069673..e4b46423a7 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/TeamBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/TeamBusinessService.java @@ -12,13 +12,12 @@ import ch.puzzle.okr.service.persistence.UserTeamPersistenceService; import ch.puzzle.okr.service.validation.TeamValidationService; import jakarta.transaction.Transactional; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Objects; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class TeamBusinessService { @@ -35,9 +34,9 @@ public class TeamBusinessService { private final CacheService cacheService; public TeamBusinessService(TeamPersistenceService teamPersistenceService, - ObjectiveBusinessService objectiveBusinessService, TeamValidationService validator, - CacheService cacheService, UserPersistenceService userPersistenceService, - UserTeamPersistenceService userTeamPersistenceService) { + ObjectiveBusinessService objectiveBusinessService, TeamValidationService validator, + CacheService cacheService, UserPersistenceService userPersistenceService, + UserTeamPersistenceService userTeamPersistenceService) { this.teamPersistenceService = teamPersistenceService; this.objectiveBusinessService = objectiveBusinessService; this.userPersistenceService = userPersistenceService; @@ -52,7 +51,8 @@ public Team getTeamById(Long teamId) { } @Transactional - // Creates a new team. Current authorization user is added as admin user in team. + // Creates a new team. Current authorization user is added as admin user in + // team. public Team createTeam(Team team, AuthorizationUser authorizationUser) { validator.validateOnCreate(team); cacheService.emptyAuthorizationUsersCache(); @@ -72,7 +72,8 @@ public Team updateTeam(Team team, Long id) { @Transactional public void deleteTeam(Long id) { validator.validateOnDelete(id); - objectiveBusinessService.getEntitiesByTeamId(id) + objectiveBusinessService + .getEntitiesByTeamId(id) .forEach(objective -> objectiveBusinessService.deleteEntityById(objective.getId())); deleteUserTeamList(id); cacheService.emptyAuthorizationUsersCache(); @@ -81,7 +82,8 @@ public void deleteTeam(Long id) { private void deleteUserTeamList(Long id) { var team = teamPersistenceService.findById(id); - // remove userTeam from each user, otherwise they are still in the session and are not deleted + // remove userTeam from each user, otherwise they are still in the session and + // are not deleted team.getUserTeamList().forEach(userTeam -> { var user = userTeam.getUser(); user.getUserTeamList().remove(userTeam); @@ -122,9 +124,12 @@ public void removeUserFromTeam(long teamId, long userId) { checkTeamHasAtLeastOneAdmin(team, user); var userTeamList = user.getUserTeamList(); - var userTeamToRemove = userTeamList.stream().filter(ut -> ut.getTeam().getId() == teamId).findFirst() + var userTeamToRemove = userTeamList + .stream() + .filter(ut -> ut.getTeam().getId() == teamId) + .findFirst() .orElseThrow(() -> new OkrResponseStatusException(HttpStatus.BAD_REQUEST, - "No team found to remove from userTeam list")); + "No team found to remove from userTeam list")); userTeamList.remove(userTeamToRemove); team.getUserTeamList().remove(userTeamToRemove); userTeamPersistenceService.delete(userTeamToRemove); @@ -133,10 +138,13 @@ public void removeUserFromTeam(long teamId, long userId) { } private void checkTeamHasAtLeastOneAdmin(Team team, User user) { - team.getUserTeamList().stream() - .filter(ut -> ut.isTeamAdmin() && !Objects.equals(ut.getUser().getId(), user.getId())).findAny() + team + .getUserTeamList() + .stream() + .filter(ut -> ut.isTeamAdmin() && !Objects.equals(ut.getUser().getId(), user.getId())) + .findAny() .orElseThrow(() -> new OkrResponseStatusException(HttpStatus.BAD_REQUEST, - ErrorKey.TRIED_TO_DELETE_LAST_ADMIN)); + ErrorKey.TRIED_TO_DELETE_LAST_ADMIN)); } @Transactional diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java index cfb7d3901e..3bb9a10d54 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java @@ -7,12 +7,11 @@ import ch.puzzle.okr.service.persistence.UserPersistenceService; import ch.puzzle.okr.service.validation.UserValidationService; import jakarta.transaction.Transactional; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; import java.util.stream.StreamSupport; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class UserBusinessService { @@ -24,7 +23,7 @@ public class UserBusinessService { private final CacheService cacheService; public UserBusinessService(UserPersistenceService userPersistenceService, UserValidationService validationService, - CacheService cacheService) { + CacheService cacheService) { this.userPersistenceService = userPersistenceService; this.validationService = validationService; this.cacheService = cacheService; @@ -55,9 +54,12 @@ public User setIsOkrChampion(User user, boolean okrChampion) { // checks if at least one okr champion remains after removing given one private void checkAtLeastOneOkrChampionExists(User user) { var champions = userPersistenceService.findAllOkrChampions(); - champions.stream().filter(c -> c.isOkrChampion() && !Objects.equals(c.getId(), user.getId())).findAny() + champions + .stream() + .filter(c -> c.isOkrChampion() && !Objects.equals(c.getId(), user.getId())) + .findAny() .orElseThrow(() -> new OkrResponseStatusException(HttpStatus.BAD_REQUEST, - ErrorKey.TRIED_TO_REMOVE_LAST_OKR_CHAMPION)); + ErrorKey.TRIED_TO_REMOVE_LAST_OKR_CHAMPION)); } public User saveUser(User user) { diff --git a/backend/src/main/java/ch/puzzle/okr/service/clientconfig/ClientConfigService.java b/backend/src/main/java/ch/puzzle/okr/service/clientconfig/ClientConfigService.java index 0b83fd2f4a..29cc6ab69d 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/clientconfig/ClientConfigService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/clientconfig/ClientConfigService.java @@ -5,14 +5,13 @@ import ch.puzzle.okr.multitenancy.customization.TenantClientCustomization; import ch.puzzle.okr.multitenancy.customization.TenantClientCustomizationProvider; import jakarta.persistence.EntityNotFoundException; +import java.text.MessageFormat; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.text.MessageFormat; -import java.util.Optional; - @Service public class ClientConfigService { @@ -24,7 +23,7 @@ public class ClientConfigService { private String activeProfile; public ClientConfigService(final TenantClientCustomizationProvider clientCustomizationProvider, - final TenantConfigProvider tenantConfigProvider) { + final TenantConfigProvider tenantConfigProvider) { this.tenantConfigProvider = tenantConfigProvider; this.tenantClientCustomizationProvider = clientCustomizationProvider; } @@ -33,32 +32,34 @@ public ClientConfigDto getConfigBasedOnActiveEnv(String hostName) { String subdomain = hostName.split("\\.")[0]; String domainPrefixByHyphen = hostName.split("-")[0]; - Optional tenantConfig = getTenantConfig(hostName, subdomain, - domainPrefixByHyphen); + Optional tenantConfig = getTenantConfig(hostName, + subdomain, + domainPrefixByHyphen); if (tenantConfig.isEmpty()) { - throw new EntityNotFoundException( - MessageFormat.format("Could not find tenant config for subdomain:{0}", subdomain)); + throw new EntityNotFoundException(MessageFormat + .format("Could not find tenant config for subdomain:{0}", subdomain)); } Optional tenantClientCustomization = getTenantClientCustomization(hostName, - subdomain, domainPrefixByHyphen); + subdomain, + domainPrefixByHyphen); if (tenantClientCustomization.isEmpty()) { - throw new EntityNotFoundException( - MessageFormat.format("Could not find tenant client customization for subdomain:{0}", subdomain)); + throw new EntityNotFoundException(MessageFormat + .format("Could not find tenant client customization for subdomain:{0}", subdomain)); } return new ClientConfigDto(activeProfile, // - tenantConfig.get().issuerUrl(), // - tenantConfig.get().clientId(), // - tenantClientCustomization.get().favicon(), // - tenantClientCustomization.get().logo(), // - tenantClientCustomization.get().triangles(), // - tenantClientCustomization.get().backgroundLogo(), // - tenantClientCustomization.get().title(), // - tenantClientCustomization.get().helpSiteUrl(), // - tenantClientCustomization.get().customStyles()); // + tenantConfig.get().issuerUrl(), // + tenantConfig.get().clientId(), // + tenantClientCustomization.get().favicon(), // + tenantClientCustomization.get().logo(), // + tenantClientCustomization.get().triangles(), // + tenantClientCustomization.get().backgroundLogo(), // + tenantClientCustomization.get().title(), // + tenantClientCustomization.get().helpSiteUrl(), // + tenantClientCustomization.get().customStyles()); // } private Optional getTenantConfig(String hostname, String... tenantsFromUrl) { @@ -75,7 +76,7 @@ private Optional getTenantConfig(String hostn } private Optional getTenantClientCustomization(String hostname, - String... tenantsFromUrl) { + String... tenantsFromUrl) { for (String tenant : tenantsFromUrl) { Optional tenantCustomization = tenantClientCustomizationProvider .getTenantClientCustomizationsById(tenant); diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/ActionPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/ActionPersistenceService.java index 3c3a1ff83c..2ceb3685fe 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/ActionPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/ActionPersistenceService.java @@ -1,12 +1,11 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.ACTION; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.repository.ActionRepository; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.ACTION; +import org.springframework.stereotype.Service; @Service public class ActionPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceService.java index 03bb2ad444..e3451cb05a 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceService.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.ALIGNMENT; + import ch.puzzle.okr.models.alignment.Alignment; import ch.puzzle.okr.models.alignment.KeyResultAlignment; import ch.puzzle.okr.models.alignment.ObjectiveAlignment; import ch.puzzle.okr.repository.AlignmentRepository; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.ALIGNMENT; +import org.springframework.stereotype.Service; @Service public class AlignmentPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceService.java index 3a439073b8..b460372231 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceService.java @@ -2,9 +2,8 @@ import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.repository.AlignmentSelectionRepository; -import org.springframework.stereotype.Service; - import java.util.List; +import org.springframework.stereotype.Service; @Service public class AlignmentSelectionPersistenceService { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/AuthorizationCriteria.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/AuthorizationCriteria.java index 50649665db..02a5dbc7ed 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/AuthorizationCriteria.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/AuthorizationCriteria.java @@ -1,17 +1,16 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.models.State.*; +import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; +import static java.lang.String.format; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import jakarta.persistence.TypedQuery; +import java.util.List; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.List; - -import static ch.puzzle.okr.models.State.*; -import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; -import static java.lang.String.format; - @Component public class AuthorizationCriteria { @@ -29,8 +28,9 @@ public String appendOverview(List teamIds, String objectiveQuery, Authoriz sb.append("\n and o.overviewId.teamId in (:" + PARAM_TEAM_IDS + ")"); } if (shouldAddObjectiveFilter(objectiveQuery)) { - sb.append("\n and lower(coalesce(o.objectiveTitle, '')) like lower(concat('%',:" + PARAM_OBJECTIVE_QUERY - + ",'%'))"); + sb + .append("\n and lower(coalesce(o.objectiveTitle, '')) like lower(concat('%',:" + + PARAM_OBJECTIVE_QUERY + ",'%'))"); } String authorizationWhereClause = append(user, alias, "objectiveState", "overviewId.teamId"); if (!authorizationWhereClause.isEmpty()) { @@ -50,8 +50,14 @@ private String append(AuthorizationUser user, String alias, String stateColumn, sb.append(format(" or %s.%s=:%s", alias, stateColumn, PARAM_ALL_DRAFT_STATE)); } else { // users can read draft state of teams with admin role - sb.append(format(" or (%s.%s=:%s and %s.%s IN (:%s))", alias, stateColumn, PARAM_TEAM_DRAFT_STATE, alias, - teamIdColumn, PARAM_USER_TEAM_IDS)); + sb + .append(format(" or (%s.%s=:%s and %s.%s IN (:%s))", + alias, + stateColumn, + PARAM_TEAM_DRAFT_STATE, + alias, + teamIdColumn, + PARAM_USER_TEAM_IDS)); } // all users can read published state sb.append(format(" or %s.%s IN (:%s)", alias, stateColumn, PARAM_PUBLISHED_STATES)); @@ -62,7 +68,7 @@ private String append(AuthorizationUser user, String alias, String stateColumn, } public void setParameters(TypedQuery typedQuery, List teamIds, String objectiveQuery, - AuthorizationUser user) { + AuthorizationUser user) { if (shouldAddTeamFilter(teamIds)) { typedQuery.setParameter(PARAM_TEAM_IDS, teamIds); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/CheckInPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/CheckInPersistenceService.java index 5a96b8dcb5..8beee6fd3b 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/CheckInPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/CheckInPersistenceService.java @@ -1,12 +1,11 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.CHECK_IN; + import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.repository.CheckInRepository; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.CHECK_IN; +import org.springframework.stereotype.Service; @Service public class CheckInPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/CompletedPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/CompletedPersistenceService.java index 48a5d2c195..4741bde78e 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/CompletedPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/CompletedPersistenceService.java @@ -1,11 +1,11 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.COMPLETED; + import ch.puzzle.okr.models.Completed; import ch.puzzle.okr.repository.CompletedRepository; import org.springframework.stereotype.Service; -import static ch.puzzle.okr.Constants.COMPLETED; - @Service public class CompletedPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceService.java index 392ef8266e..03e31dabb6 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceService.java @@ -1,16 +1,15 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.KEY_RESULT; + import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.repository.KeyResultRepository; import jakarta.transaction.Transactional; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import java.util.List; - -import static ch.puzzle.okr.Constants.KEY_RESULT; - @Service public class KeyResultPersistenceService extends PersistenceBase { private static final Logger logger = LoggerFactory.getLogger(KeyResultPersistenceService.class); @@ -43,7 +42,8 @@ public KeyResult updateEntity(KeyResult keyResult) { } public List getKeyResultsOwnedByUser(long userId) { - return findAll().stream() // + return findAll() + .stream() // .filter(keyResult -> keyResult.getOwner().getId().equals(userId)) // .toList(); } diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceService.java index 9e7a2bcd34..aac01d8da1 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceService.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.OBJECTIVE; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.Quarter; @@ -9,14 +11,11 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.NoResultException; import jakarta.persistence.TypedQuery; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import java.util.List; - -import static ch.puzzle.okr.Constants.OBJECTIVE; - @Service public class ObjectivePersistenceService extends PersistenceBase { @@ -29,7 +28,7 @@ public class ObjectivePersistenceService extends PersistenceBase authorizationCriteria; protected ObjectivePersistenceService(ObjectiveRepository repository, EntityManager entityManager, - AuthorizationCriteria authorizationCriteria) { + AuthorizationCriteria authorizationCriteria) { super(repository); this.entityManager = entityManager; this.authorizationCriteria = authorizationCriteria; @@ -41,8 +40,9 @@ public String getModelName() { } /** - * Get the number of Objectives of a Team in a Quarter. The underling sql looks like "select count(*) from objective - * where teamId = team.id and quarterId = quarter.id." + * Get the number of Objectives of a Team in a Quarter. The underling sql looks + * like "select count(*) from objective where teamId = team.id and quarterId = + * quarter.id." * * @param team * Team @@ -56,7 +56,7 @@ public Integer countByTeamAndQuarter(Team team, Quarter quarter) { } public Objective findObjectiveById(Long objectiveId, AuthorizationUser authorizationUser, - OkrResponseStatusException noResultException) { + OkrResponseStatusException noResultException) { return findByAnyId(objectiveId, authorizationUser, SELECT_OBJECTIVE_BY_ID, noResultException); } @@ -65,17 +65,17 @@ public List findObjectiveByTeamId(Long teamId) { } public Objective findObjectiveByKeyResultId(Long keyResultId, AuthorizationUser authorizationUser, - OkrResponseStatusException noResultException) { + OkrResponseStatusException noResultException) { return findByAnyId(keyResultId, authorizationUser, SELECT_OBJECTIVE_BY_KEY_RESULT_ID, noResultException); } public Objective findObjectiveByCheckInId(Long checkInId, AuthorizationUser authorizationUser, - OkrResponseStatusException noResultException) { + OkrResponseStatusException noResultException) { return findByAnyId(checkInId, authorizationUser, SELECT_OBJECTIVE_BY_CHECK_IN_ID, noResultException); } private Objective findByAnyId(Long id, AuthorizationUser authorizationUser, String queryString, - OkrResponseStatusException noResultException) { + OkrResponseStatusException noResultException) { checkIdNull(id); String fullQueryString = queryString + authorizationCriteria.appendObjective(authorizationUser); logger.debug("select objective by id={}: {}", id, fullQueryString); diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/OverviewPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/OverviewPersistenceService.java index 197cdc5d9d..6d2a2800b6 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/OverviewPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/OverviewPersistenceService.java @@ -4,12 +4,11 @@ import ch.puzzle.okr.models.overview.Overview; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import java.util.List; - @Service public class OverviewPersistenceService { @@ -20,15 +19,15 @@ public class OverviewPersistenceService { private final AuthorizationCriteria authorizationCriteria; public OverviewPersistenceService(EntityManager entityManager, - AuthorizationCriteria authorizationCriteria) { + AuthorizationCriteria authorizationCriteria) { this.entityManager = entityManager; this.authorizationCriteria = authorizationCriteria; } public List getFilteredOverview(Long quarterId, List teamIds, String objectiveQuery, - AuthorizationUser authorizationUser) { + AuthorizationUser authorizationUser) { String queryString = SELECT_OVERVIEW - + authorizationCriteria.appendOverview(teamIds, objectiveQuery, authorizationUser); + + authorizationCriteria.appendOverview(teamIds, objectiveQuery, authorizationUser); logger.debug("select overview by quarterId={} and teamIds={}: {}", quarterId, teamIds, queryString); TypedQuery typedQuery = entityManager.createQuery(queryString, Overview.class); typedQuery.setParameter("quarterId", quarterId); diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/PersistenceBase.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/PersistenceBase.java index f10ea423fc..0ca16dc599 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/PersistenceBase.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/PersistenceBase.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.service.persistence; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.NOT_FOUND; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.StreamSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.repository.CrudRepository; import org.springframework.http.HttpStatus; -import java.util.List; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.StreamSupport; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.NOT_FOUND; - /** * @param * the Type or entity of the repository @@ -59,8 +58,9 @@ public T save(T model) throws OkrResponseStatusException { return repository.save(model); } catch (OptimisticLockingFailureException ex) { logger.info("optimistic locking exception while saving {}", model, ex); - throw new OkrResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, ErrorKey.DATA_HAS_BEEN_UPDATED, - getModelName()); + throw new OkrResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, + ErrorKey.DATA_HAS_BEEN_UPDATED, + getModelName()); } } @@ -76,6 +76,7 @@ public void deleteById(ID id) { private List iteratorToList(Iterable iterable) { return StreamSupport - .stream(Spliterators.spliteratorUnknownSize(iterable.iterator(), Spliterator.ORDERED), false).toList(); + .stream(Spliterators.spliteratorUnknownSize(iterable.iterator(), Spliterator.ORDERED), false) + .toList(); } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/QuarterPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/QuarterPersistenceService.java index 5646a15998..d9e4d938ab 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/QuarterPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/QuarterPersistenceService.java @@ -1,13 +1,12 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.QUARTER; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.repository.QuarterRepository; -import org.springframework.stereotype.Service; - import java.time.LocalDate; import java.util.List; - -import static ch.puzzle.okr.Constants.QUARTER; +import org.springframework.stereotype.Service; @Service public class QuarterPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/TeamPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/TeamPersistenceService.java index 533949d848..dd485164aa 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/TeamPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/TeamPersistenceService.java @@ -1,12 +1,11 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.TEAM; + import ch.puzzle.okr.models.Team; import ch.puzzle.okr.repository.TeamRepository; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.TEAM; +import org.springframework.stereotype.Service; @Service public class TeamPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java index 6d5befc699..2cfa105ec8 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java @@ -1,13 +1,12 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.USER; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.repository.UserRepository; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Optional; - -import static ch.puzzle.okr.Constants.USER; +import org.springframework.stereotype.Service; @Service public class UserPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceService.java index 326feabe4d..8bb03cd758 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceService.java @@ -1,12 +1,11 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.USER_TEAM; + import ch.puzzle.okr.models.UserTeam; import ch.puzzle.okr.repository.UserTeamRepository; -import org.springframework.stereotype.Service; - import java.util.List; - -import static ch.puzzle.okr.Constants.USER_TEAM; +import org.springframework.stereotype.Service; @Service public class UserTeamPersistenceService extends PersistenceBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/ActionValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/ActionValidationService.java index 4e591099ff..94b9af0e89 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/ActionValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/ActionValidationService.java @@ -7,11 +7,10 @@ import ch.puzzle.okr.models.MessageKey; import ch.puzzle.okr.repository.ActionRepository; import ch.puzzle.okr.service.persistence.ActionPersistenceService; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class ActionValidationService extends ValidationBase { @@ -19,7 +18,7 @@ public class ActionValidationService extends ValidationBase { + extends + ValidationBase { AlignmentValidationService(AlignmentPersistenceService persistenceService) { super(persistenceService); diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/CheckInValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/CheckInValidationService.java index 87f3f14839..b1eedc6bc0 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/CheckInValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/CheckInValidationService.java @@ -6,15 +6,15 @@ import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.repository.CheckInRepository; import ch.puzzle.okr.service.persistence.CheckInPersistenceService; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class CheckInValidationService - extends ValidationBase { + extends + ValidationBase { public CheckInValidationService(CheckInPersistenceService checkInPersistenceService) { super(checkInPersistenceService); @@ -39,8 +39,9 @@ public void validateOnUpdate(Long id, CheckIn model) { private static void throwExceptionWhenKeyResultHasChanged(CheckIn checkIn, CheckIn savedCheckIn) { if (!Objects.equals(checkIn.getKeyResult().getId(), savedCheckIn.getKeyResult().getId())) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_CANNOT_CHANGE, - List.of(Constants.KEY_RESULT, Constants.CHECK_IN)); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_CANNOT_CHANGE, + List.of(Constants.KEY_RESULT, Constants.CHECK_IN)); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/CompletedValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/CompletedValidationService.java index 702db8e4d7..178ef9019e 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/CompletedValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/CompletedValidationService.java @@ -7,7 +7,8 @@ @Service public class CompletedValidationService - extends ValidationBase { + extends + ValidationBase { public CompletedValidationService(CompletedPersistenceService completedPersistenceService) { super(completedPersistenceService); diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/KeyResultValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/KeyResultValidationService.java index ea5a3b68e9..8f4795fb1c 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/KeyResultValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/KeyResultValidationService.java @@ -6,15 +6,15 @@ import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.repository.KeyResultRepository; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class KeyResultValidationService - extends ValidationBase { + extends + ValidationBase { public KeyResultValidationService(KeyResultPersistenceService keyResultPersistenceService) { super(keyResultPersistenceService); @@ -39,8 +39,9 @@ public void validateOnUpdate(Long id, KeyResult model) { private static void throwExceptionWhenObjectiveHasChanged(KeyResult keyResult, KeyResult savedKeyResult) { if (!Objects.equals(keyResult.getObjective().getId(), savedKeyResult.getObjective().getId())) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_CANNOT_CHANGE, - List.of(Constants.OBJECTIVE, Constants.KEY_RESULT)); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_CANNOT_CHANGE, + List.of(Constants.OBJECTIVE, Constants.KEY_RESULT)); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/ObjectiveValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/ObjectiveValidationService.java index 72f518c738..e2761c17c8 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/ObjectiveValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/ObjectiveValidationService.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.*; +import static ch.puzzle.okr.service.validation.QuarterValidationService.throwExceptionWhenStartEndDateQuarterIsNull; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -7,18 +10,15 @@ import ch.puzzle.okr.models.Team; import ch.puzzle.okr.repository.ObjectiveRepository; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; - -import static ch.puzzle.okr.Constants.*; -import static ch.puzzle.okr.service.validation.QuarterValidationService.throwExceptionWhenStartEndDateQuarterIsNull; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class ObjectiveValidationService - extends ValidationBase { + extends + ValidationBase { public ObjectiveValidationService(ObjectivePersistenceService objectivePersistenceService) { super(objectivePersistenceService); @@ -49,36 +49,40 @@ public void validateOnUpdate(Long id, Objective model) { private void throwExceptionWhenModifiedByIsSet(Objective model) { if (model.getModifiedBy() != null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_SET_FORBIDDEN, - List.of("ModifiedBy", model.getModifiedBy())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_SET_FORBIDDEN, + List.of("ModifiedBy", model.getModifiedBy())); } } private void throwExceptionWhenModifiedByIsNull(Objective model) { if (model.getModifiedBy() == null) { - throw new OkrResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, ErrorKey.ATTRIBUTE_NOT_SET, - "modifiedBy"); + throw new OkrResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, + ErrorKey.ATTRIBUTE_NOT_SET, + "modifiedBy"); } } private void throwExceptionWhenTeamHasChanged(Team team, Team savedTeam) { if (!Objects.equals(team, savedTeam)) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_CANNOT_CHANGE, - List.of(TEAM, OBJECTIVE)); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_CANNOT_CHANGE, + List.of(TEAM, OBJECTIVE)); } } private void throwExceptionWhenNotDraftInBacklogQuarter(Objective model) { if (isInvalidBacklogObjective(model)) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_MUST_BE_DRAFT, - List.of(OBJECTIVE, STATE_DRAFT, model.getState())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_MUST_BE_DRAFT, + List.of(OBJECTIVE, STATE_DRAFT, model.getState())); } } private boolean isInvalidBacklogObjective(Objective model) { return model.getQuarter().getLabel().equals(BACK_LOG_QUARTER_LABEL) // - && model.getQuarter().getStartDate() == null // - && model.getQuarter().getEndDate() == null // - && (model.getState() != State.DRAFT); + && model.getQuarter().getStartDate() == null // + && model.getQuarter().getEndDate() == null // + && (model.getState() != State.DRAFT); } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/OverviewValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/OverviewValidationService.java index af0013b52d..1ff7e18fdf 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/OverviewValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/OverviewValidationService.java @@ -1,7 +1,7 @@ package ch.puzzle.okr.service.validation; -import org.springframework.stereotype.Service; import java.util.List; +import org.springframework.stereotype.Service; @Service public class OverviewValidationService { diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/QuarterValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/QuarterValidationService.java index baa9df7252..4f1d47787b 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/QuarterValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/QuarterValidationService.java @@ -1,20 +1,20 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.repository.QuarterRepository; import ch.puzzle.okr.service.persistence.QuarterPersistenceService; +import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import java.util.List; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; - @Service public class QuarterValidationService - extends ValidationBase { + extends + ValidationBase { public QuarterValidationService(QuarterPersistenceService quarterPersistenceService) { super(quarterPersistenceService); @@ -33,11 +33,13 @@ public void validateOnUpdate(Long id, Quarter model) { public static void throwExceptionWhenStartEndDateQuarterIsNull(Quarter model) { if (!model.getLabel().equals(BACK_LOG_QUARTER_LABEL)) { if (model.getStartDate() == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_NULL, - List.of("StartDate", model.getLabel())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_NULL, + List.of("StartDate", model.getLabel())); } else if (model.getEndDate() == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_NULL, - List.of("EndDate", model.getLabel())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_NULL, + List.of("EndDate", model.getLabel())); } } @@ -45,11 +47,13 @@ public static void throwExceptionWhenStartEndDateQuarterIsNull(Quarter model) { public void validateOnGeneration(Quarter quarter) { if (quarter.getStartDate() == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_NULL, - List.of("StartDate", quarter.getLabel())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_NULL, + List.of("StartDate", quarter.getLabel())); } else if (quarter.getEndDate() == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_NULL, - List.of("EndDate", quarter.getLabel())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_NULL, + List.of("EndDate", quarter.getLabel())); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/TeamValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/TeamValidationService.java index 8b08e1d4a2..560d61d2fe 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/TeamValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/TeamValidationService.java @@ -1,17 +1,16 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.TEAM; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.repository.TeamRepository; import ch.puzzle.okr.service.persistence.TeamPersistenceService; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - import java.util.List; import java.util.Objects; - -import static ch.puzzle.okr.Constants.TEAM; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; @Service public class TeamValidationService extends ValidationBase { @@ -39,11 +38,16 @@ public void validateOnUpdate(Long id, Team model) { } private void checkIfTeamWithNameAlreadyExists(String name, Long id) { - List filteredTeam = this.getPersistenceService().findTeamsByName(name).stream() - .filter(team -> !Objects.equals(team.getId(), id)).toList(); + List filteredTeam = this + .getPersistenceService() + .findTeamsByName(name) + .stream() + .filter(team -> !Objects.equals(team.getId(), id)) + .toList(); if (!filteredTeam.isEmpty()) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ALREADY_EXISTS_SAME_NAME, - List.of(TEAM, name)); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ALREADY_EXISTS_SAME_NAME, + List.of(TEAM, name)); } } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/UserValidationService.java b/backend/src/main/java/ch/puzzle/okr/service/validation/UserValidationService.java index 487530aa3e..b2ed76eabf 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/UserValidationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/UserValidationService.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.service.validation; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; @@ -10,8 +12,6 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.stereotype.Service; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @Service public class UserValidationService extends ValidationBase { diff --git a/backend/src/main/java/ch/puzzle/okr/service/validation/ValidationBase.java b/backend/src/main/java/ch/puzzle/okr/service/validation/ValidationBase.java index e18cd9e982..e93ada1ba1 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/validation/ValidationBase.java +++ b/backend/src/main/java/ch/puzzle/okr/service/validation/ValidationBase.java @@ -9,14 +9,13 @@ import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; -import org.springframework.http.HttpStatus; - import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.http.HttpStatus; /** * @param @@ -62,29 +61,33 @@ public T doesEntityExist(ID id) { public void throwExceptionWhenModelIsNull(T model) { if (model == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.MODEL_NULL, - persistenceService.getModelName()); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.MODEL_NULL, + persistenceService.getModelName()); } } public void throwExceptionWhenIdIsNull(ID id) { if (id == null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_NULL, - List.of("ID", persistenceService.getModelName())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_NULL, + List.of("ID", persistenceService.getModelName())); } } protected void throwExceptionWhenIdIsNotNull(ID id) { if (id != null) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, MessageKey.ATTRIBUTE_NOT_NULL, - List.of("ID", persistenceService.getModelName())); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + MessageKey.ATTRIBUTE_NOT_NULL, + List.of("ID", persistenceService.getModelName())); } } protected void throwExceptionWhenIdHasChanged(ID id, ID modelId) { if (!Objects.equals(id, modelId)) { - throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, ErrorKey.ATTRIBUTE_CHANGED, - List.of("ID", id, modelId)); + throw new OkrResponseStatusException(HttpStatus.BAD_REQUEST, + ErrorKey.ATTRIBUTE_CHANGED, + List.of("ID", id, modelId)); } } @@ -101,14 +104,16 @@ private void processViolations(Set> violations) { } private List createErrorDtos(Set> violations) { - return violations.stream() // + return violations + .stream() // .map(e -> { // String path = e.getPropertyPath().toString(); // List attributes = new ArrayList<>(List.of(path, persistenceService.getModelName())); // attributes.addAll(getAttributes(e.getMessage(), e.getMessageTemplate())); // String errorKey = e.getMessageTemplate().replaceAll("_\\{.*", ""); // return ErrorDto.of(errorKey, attributes); // - }).toList(); + }) + .toList(); } // example: diff --git a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterData.java b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterData.java index 2bab507122..e4bf233d1e 100644 --- a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterData.java +++ b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterData.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.util.quarter.generate; -import org.springframework.context.annotation.Profile; - import java.time.LocalDate; +import org.springframework.context.annotation.Profile; /** * Quarter data for H2 database.
*
- * This class is used for testing purposes only. Do NOT use this class in production mode. + * This class is used for testing purposes only. Do NOT use this class in + * production mode. */ @Profile("integration-test") public record QuarterData(String label, LocalDate startDate, LocalDate endDate) { @@ -30,9 +30,9 @@ private String isoFormat(LocalDate date) { @Override public String toString() { return "(" + "'" + label() + "', " + // - "'" + startDateAsIsoString() + "', " + // - "'" + endDateAsIsoString() + "'" + // - ")"; + "'" + startDateAsIsoString() + "', " + // + "'" + endDateAsIsoString() + "'" + // + ")"; } } diff --git a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterLabel.java b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterLabel.java index 4b44aaf00b..85f6e36b8c 100644 --- a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterLabel.java +++ b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/QuarterLabel.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.util.quarter.generate; -import org.springframework.context.annotation.Profile; - import java.time.LocalDate; +import org.springframework.context.annotation.Profile; /** * Quarter label for H2 database.
*
- * This class is used for testing purposes only. Do NOT use this class in production mode. + * This class is used for testing purposes only. Do NOT use this class in + * production mode. */ @Profile("integration-test") public class QuarterLabel { @@ -19,9 +19,9 @@ public QuarterLabel(LocalDate date) { public String label() { return "GJ " + // - formatYearAs2Digits(firstYearOfGeschaeftsJahr()) + "/" + // - formatYearAs2Digits(secondYearOfGeschaeftsJahr()) + "-Q" + // - getQuarterDigit(); + formatYearAs2Digits(firstYearOfGeschaeftsJahr()) + "/" + // + formatYearAs2Digits(secondYearOfGeschaeftsJahr()) + "-Q" + // + getQuarterDigit(); } private int getQuarterDigit() { diff --git a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/Quarters.java b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/Quarters.java index 0c7679714b..d7dcc53f12 100644 --- a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/Quarters.java +++ b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/Quarters.java @@ -1,15 +1,15 @@ package ch.puzzle.okr.util.quarter.generate; -import org.springframework.context.annotation.Profile; - import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import org.springframework.context.annotation.Profile; /** * Static initialize quarters for H2 database.
*
- * This class is used for testing purposes only. Do NOT use this class in production mode. + * This class is used for testing purposes only. Do NOT use this class in + * production mode. */ @Profile("integration-test") public class Quarters { diff --git a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunction.java b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunction.java index fec72a232a..563b7e4f29 100644 --- a/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunction.java +++ b/backend/src/main/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunction.java @@ -2,19 +2,19 @@ import ch.puzzle.okr.util.quarter.generate.QuarterData; import ch.puzzle.okr.util.quarter.generate.Quarters; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.Map; - /** * Quarter functions for H2 database.
*
- * This class is used for testing purposes only. Do NOT use this class in production mode. + * This class is used for testing purposes only. Do NOT use this class in + * production mode. */ @Component @Profile("integration-test") diff --git a/backend/src/test/java/ch/puzzle/okr/ForwardFilterTest.java b/backend/src/test/java/ch/puzzle/okr/ForwardFilterTest.java index 1c27667c3e..81fe66f00c 100644 --- a/backend/src/test/java/ch/puzzle/okr/ForwardFilterTest.java +++ b/backend/src/test/java/ch/puzzle/okr/ForwardFilterTest.java @@ -1,12 +1,14 @@ package ch.puzzle.okr; +import static org.mockito.Mockito.*; + import jakarta.servlet.FilterChain; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -15,10 +17,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.IOException; - -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class ForwardFilterTest { @InjectMocks diff --git a/backend/src/test/java/ch/puzzle/okr/SpringCachingConfigTest.java b/backend/src/test/java/ch/puzzle/okr/SpringCachingConfigTest.java index 1ca5d0825a..0d4001cd23 100644 --- a/backend/src/test/java/ch/puzzle/okr/SpringCachingConfigTest.java +++ b/backend/src/test/java/ch/puzzle/okr/SpringCachingConfigTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr; +import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; +import static ch.puzzle.okr.test.TestHelper.defaultUser; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.multitenancy.TenantContext; @@ -14,10 +18,6 @@ import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; -import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; -import static ch.puzzle.okr.test.TestHelper.defaultUser; -import static org.junit.jupiter.api.Assertions.*; - @SpringIntegrationTest class SpringCachingConfigTest { @@ -64,12 +64,12 @@ void testUserIsCached() { } private void assertEqualUsers(AuthorizationUser expectedAuthorizationUser, - AuthorizationUser actualAuthorizationUser) { + AuthorizationUser actualAuthorizationUser) { User expcetedUser = expectedAuthorizationUser.user(); User actualUser = actualAuthorizationUser.user(); assertTrue(expcetedUser.getFirstname().equals(actualUser.getFirstname()) - && expcetedUser.getLastname().equals(actualUser.getLastname()) - && expcetedUser.getEmail().equals(actualUser.getEmail())); + && expcetedUser.getLastname().equals(actualUser.getLastname()) + && expcetedUser.getEmail().equals(actualUser.getEmail())); } } \ No newline at end of file diff --git a/backend/src/test/java/ch/puzzle/okr/UserKeyGeneratorTest.java b/backend/src/test/java/ch/puzzle/okr/UserKeyGeneratorTest.java index 05d38792e5..511dc51dc3 100644 --- a/backend/src/test/java/ch/puzzle/okr/UserKeyGeneratorTest.java +++ b/backend/src/test/java/ch/puzzle/okr/UserKeyGeneratorTest.java @@ -1,14 +1,13 @@ package ch.puzzle.okr; +import static ch.puzzle.okr.test.KeyResultTestHelpers.user; + import ch.puzzle.okr.multitenancy.TenantContext; +import java.lang.reflect.Method; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.lang.reflect.Method; - -import static ch.puzzle.okr.test.KeyResultTestHelpers.user; - class UserKeyGeneratorTest { @BeforeEach diff --git a/backend/src/test/java/ch/puzzle/okr/architecture/OkrArchitectureTest.java b/backend/src/test/java/ch/puzzle/okr/architecture/OkrArchitectureTest.java index 9ea2c7511b..449f9a640b 100644 --- a/backend/src/test/java/ch/puzzle/okr/architecture/OkrArchitectureTest.java +++ b/backend/src/test/java/ch/puzzle/okr/architecture/OkrArchitectureTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.architecture; +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; +import static com.tngtech.archunit.library.Architectures.layeredArchitecture; + import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.core.importer.ImportOption; @@ -13,17 +17,19 @@ import org.springframework.stereotype.*; import org.springframework.web.bind.annotation.RestController; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; -import static com.tngtech.archunit.library.Architectures.layeredArchitecture; - class OkrArchitectureTest { @Test void repositoryAccessedOnlyByPersistenceService() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().resideInAPackage("..repository..").should().onlyBeAccessed() - .byAnyPackage("..service.persistence..").andShould().beInterfaces(); + ArchRule rule = classes() + .that() + .resideInAPackage("..repository..") + .should() + .onlyBeAccessed() + .byAnyPackage("..service.persistence..") + .andShould() + .beInterfaces(); rule.check(importedClasses); } @@ -31,7 +37,11 @@ void repositoryAccessedOnlyByPersistenceService() { @Test void mapperAccessedByControllerOrAuthorization() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().resideInAPackage("..mapper..").should().onlyBeAccessed() + ArchRule rule = classes() + .that() + .resideInAPackage("..mapper..") + .should() + .onlyBeAccessed() .byAnyPackage("..controller..", "..mapper..", "..authorization.."); rule.check(importedClasses); @@ -40,7 +50,11 @@ void mapperAccessedByControllerOrAuthorization() { @Test void authorizationServiceAccessedByControllerOrAuthorization() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().resideInAPackage("..service.authorization..").should().onlyBeAccessed() + ArchRule rule = classes() + .that() + .resideInAPackage("..service.authorization..") + .should() + .onlyBeAccessed() .byAnyPackage("..controller..", "..authorization.."); rule.check(importedClasses); @@ -49,7 +63,11 @@ void authorizationServiceAccessedByControllerOrAuthorization() { @Test void businessServiceAccessedByControllerOrAuthorizationServiceOrMapper() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().resideInAPackage("..service.business..").should().onlyBeAccessed() + ArchRule rule = classes() + .that() + .resideInAPackage("..service.business..") + .should() + .onlyBeAccessed() .byAnyPackage("..controller..", "..authorization..", "..mapper..", "..business", "..deserializer"); rule.check(importedClasses); @@ -59,8 +77,14 @@ void businessServiceAccessedByControllerOrAuthorizationServiceOrMapper() { void controllerCallsNoRepository() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = noClasses().that().resideInAPackage("ch.puzzle.okr.controller..").should().dependOnClassesThat() - .resideInAPackage("..repository..").andShould().notBeInterfaces(); + ArchRule rule = noClasses() + .that() + .resideInAPackage("ch.puzzle.okr.controller..") + .should() + .dependOnClassesThat() + .resideInAPackage("..repository..") + .andShould() + .notBeInterfaces(); rule.check(importedClasses); } @@ -69,8 +93,14 @@ void controllerCallsNoRepository() { void repositoryCallsNoService() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = noClasses().that().resideInAPackage("ch.puzzle.okr.repository").should().dependOnClassesThat() - .resideInAPackage("..service..").andShould().beInterfaces(); + ArchRule rule = noClasses() + .that() + .resideInAPackage("ch.puzzle.okr.repository") + .should() + .dependOnClassesThat() + .resideInAPackage("..service..") + .andShould() + .beInterfaces(); rule.check(importedClasses); } @@ -79,8 +109,15 @@ void repositoryCallsNoService() { void servicesAreAnnotatedWithService() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().areNotAnonymousClasses().and().resideInAPackage("ch.puzzle.okr.service") - .should().beAnnotatedWith(Service.class).andShould().notBeInterfaces(); + ArchRule rule = classes() + .that() + .areNotAnonymousClasses() + .and() + .resideInAPackage("ch.puzzle.okr.service") + .should() + .beAnnotatedWith(Service.class) + .andShould() + .notBeInterfaces(); rule.check(importedClasses); } @@ -89,8 +126,16 @@ void servicesAreAnnotatedWithService() { void controllersAreAnnotatedWithRestController() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().areNotAnonymousClasses().and().resideInAPackage("ch.puzzle.okr.controller..") - .should().beAnnotatedWith(RestController.class).orShould().beAnnotatedWith(Controller.class).andShould() + ArchRule rule = classes() + .that() + .areNotAnonymousClasses() + .and() + .resideInAPackage("ch.puzzle.okr.controller..") + .should() + .beAnnotatedWith(RestController.class) + .orShould() + .beAnnotatedWith(Controller.class) + .andShould() .notBeInterfaces(); rule.check(importedClasses); @@ -100,8 +145,15 @@ void controllersAreAnnotatedWithRestController() { void mappersAreAnnotatedWithComponent() { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().areNotAnonymousClasses().and().resideInAPackage("ch.puzzle.okr.mapper") - .should().beAnnotatedWith(Component.class).andShould().notBeInterfaces(); + ArchRule rule = classes() + .that() + .areNotAnonymousClasses() + .and() + .resideInAPackage("ch.puzzle.okr.mapper") + .should() + .beAnnotatedWith(Component.class) + .andShould() + .notBeInterfaces(); rule.check(importedClasses); } @@ -109,11 +161,19 @@ void mappersAreAnnotatedWithComponent() { @ParameterizedTest @CsvFileSource(resources = "/repositoriesAndPersistenceServices.csv", numLinesToSkip = 1) void repositoriesShouldOnlyBeCalledFromPersistenceServicesAndValidationService(String repository, - String persistenceService, String validationService) { + String persistenceService, + String validationService) { JavaClasses importedClasses = getMainSourceClasses(); - ArchRule rule = classes().that().haveSimpleName(repository).should().onlyHaveDependentClassesThat() - .haveSimpleName(persistenceService).orShould().haveSimpleName(repository).orShould() + ArchRule rule = classes() + .that() + .haveSimpleName(repository) + .should() + .onlyHaveDependentClassesThat() + .haveSimpleName(persistenceService) + .orShould() + .haveSimpleName(repository) + .orShould() .haveSimpleName(validationService); rule.check(importedClasses); @@ -124,8 +184,13 @@ void repositoriesShouldOnlyBeCalledFromPersistenceServicesAndValidationService(S void classesInRightPackages(String passedName) { JavaClasses importedClasses = new ClassFileImporter().importPackages("ch.puzzle.okr"); - ArchRule rule = classes().that().haveSimpleNameEndingWith(StringUtils.capitalize(passedName)).and() - .areTopLevelClasses().should().resideInAPackage("ch.puzzle.okr." + passedName + ".."); + ArchRule rule = classes() + .that() + .haveSimpleNameEndingWith(StringUtils.capitalize(passedName)) + .and() + .areTopLevelClasses() + .should() + .resideInAPackage("ch.puzzle.okr." + passedName + ".."); rule.check(importedClasses); } @@ -133,31 +198,48 @@ void classesInRightPackages(String passedName) { @Test void serviceLayerCheck() { JavaClasses importedClasses = getMainSourceClasses(); - Architectures.LayeredArchitecture layeredArchitecture = layeredArchitecture().consideringAllDependencies() // - .layer("Controller").definedBy("..controller..") // - .layer("AuthorizationService").definedBy("..service.authorization..") // - .layer("BusinessService").definedBy("..service.business..") // - .layer("ValidationService").definedBy("..service.validation..") // - .layer("PersistenceService").definedBy("..service.persistence..") // - .layer("Repository").definedBy("..repository..") // - .layer("Mapper").definedBy("..mapper..") // - .layer("Deserializer").definedBy("..deserializer..") // - - .whereLayer("Controller").mayNotBeAccessedByAnyLayer() // - .whereLayer("AuthorizationService").mayOnlyBeAccessedByLayers("Controller") // + Architectures.LayeredArchitecture layeredArchitecture = layeredArchitecture() + .consideringAllDependencies() // + .layer("Controller") + .definedBy("..controller..") // + .layer("AuthorizationService") + .definedBy("..service.authorization..") // + .layer("BusinessService") + .definedBy("..service.business..") // + .layer("ValidationService") + .definedBy("..service.validation..") // + .layer("PersistenceService") + .definedBy("..service.persistence..") // + .layer("Repository") + .definedBy("..repository..") // + .layer("Mapper") + .definedBy("..mapper..") // + .layer("Deserializer") + .definedBy("..deserializer..") // + + .whereLayer("Controller") + .mayNotBeAccessedByAnyLayer() // + .whereLayer("AuthorizationService") + .mayOnlyBeAccessedByLayers("Controller") // .whereLayer("BusinessService") - .mayOnlyBeAccessedByLayers("Controller", "AuthorizationService", "Mapper", "BusinessService", - "Deserializer") // - .whereLayer("ValidationService").mayOnlyBeAccessedByLayers("BusinessService") // + .mayOnlyBeAccessedByLayers("Controller", + "AuthorizationService", + "Mapper", + "BusinessService", + "Deserializer") // + .whereLayer("ValidationService") + .mayOnlyBeAccessedByLayers("BusinessService") // .whereLayer("PersistenceService") .mayOnlyBeAccessedByLayers("BusinessService", "PersistenceService", "ValidationService") // - .whereLayer("Repository").mayOnlyBeAccessedByLayers("PersistenceService"); // + .whereLayer("Repository") + .mayOnlyBeAccessedByLayers("PersistenceService"); // layeredArchitecture.check(importedClasses); } private static JavaClasses getMainSourceClasses() { - return new ClassFileImporter().withImportOption(new ImportOption.DoNotIncludeTests()) + return new ClassFileImporter() + .withImportOption(new ImportOption.DoNotIncludeTests()) .importPackages("ch.puzzle.okr"); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/ActionControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/ActionControllerIT.java index f7fececa04..c58ec40e94 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/ActionControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/ActionControllerIT.java @@ -1,9 +1,16 @@ package ch.puzzle.okr.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; + import ch.puzzle.okr.mapper.ActionMapper; import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.authorization.ActionAuthorizationService; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,14 +27,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(ActionController.class) @@ -74,15 +73,24 @@ class ActionControllerIT { @BeforeEach void setUp() { - Action action = Action.Builder.builder().withId(3L).withAction("Neues Haus").withPriority(1).withIsChecked(true) - .withKeyResult(KeyResultMetric.Builder.builder().withId(10L).withTitle("KR Title").build()).build(); + Action action = Action.Builder + .builder() + .withId(3L) + .withAction("Neues Haus") + .withPriority(1) + .withIsChecked(true) + .withKeyResult(KeyResultMetric.Builder.builder().withId(10L).withTitle("KR Title").build()) + .build(); BDDMockito.given(actionMapper.toActions(any())).willReturn(List.of(action, action)); } @Test void updateSuccessfulActions() throws Exception { - mvc.perform(put(BASEURL).content(SUCCESSFUL_UPDATE_BODY).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(BASEURL) + .content(SUCCESSFUL_UPDATE_BODY) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()); verify(actionMapper, times(1)).toActions(any()); @@ -91,8 +99,11 @@ void updateSuccessfulActions() throws Exception { @Test void updateSuccessfulOnlyOneAction() throws Exception { - mvc.perform(put(BASEURL).content(SUCCESSFUL_UPDATE_BODY_SINGLE_ACTION).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(BASEURL) + .content(SUCCESSFUL_UPDATE_BODY_SINGLE_ACTION) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()); verify(actionMapper, times(1)).toActions(any()); @@ -101,16 +112,19 @@ void updateSuccessfulOnlyOneAction() throws Exception { @Test void shouldDeleteAction() throws Exception { - mvc.perform(delete("/api/v2/action/1").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v2/action/1").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void throwExceptionWhenActionWithIdCantBeFoundWhileDeleting() throws Exception { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Action not found")).when(actionAuthorizationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Action not found")) + .when(actionAuthorizationService) .deleteActionByActionId(anyLong()); - mvc.perform(delete("/api/v2/action/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v2/action/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/AlignmentControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/AlignmentControllerIT.java index c0372930db..f9c40ae2c2 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/AlignmentControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/AlignmentControllerIT.java @@ -1,9 +1,16 @@ package ch.puzzle.okr.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.mapper.AlignmentSelectionMapper; import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.models.alignment.AlignmentSelectionId; import ch.puzzle.okr.service.business.AlignmentSelectionBusinessService; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.Test; @@ -19,14 +26,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(AlignmentController.class) @@ -39,22 +38,49 @@ class AlignmentControllerIT { private AlignmentSelectionMapper alignmentSelectionMapper; static String alignmentObjectiveName = "Objective 5"; - static List alignmentSelectionPuzzle = List.of( - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(1L, 20L)) - .withObjectiveTitle("Objective 1").withKeyResultTitle("KeyResult 20").build(), - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(1L, 40L)) - .withObjectiveTitle("Objective 1").withKeyResultTitle("KeyResult 40").build()); - static List alignmentSelectionOKR = List.of( - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(5L, 21L)) - .withObjectiveTitle(alignmentObjectiveName).withKeyResultTitle("KeyResult 21").build(), - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(5L, 41L)) - .withObjectiveTitle(alignmentObjectiveName).withKeyResultTitle("KeyResult 41").build(), - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(5L, 61L)) - .withObjectiveTitle(alignmentObjectiveName).withKeyResultTitle("KeyResult 61").build(), - AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(5L, 81L)) - .withObjectiveTitle(alignmentObjectiveName).withKeyResultTitle("KeyResult 81").build()); - static AlignmentSelection alignmentSelectionEmptyKeyResults = AlignmentSelection.Builder.builder() - .withAlignmentSelectionId(AlignmentSelectionId.of(8L, null)).withObjectiveTitle("Objective 8").build(); + static List alignmentSelectionPuzzle = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(1L, 20L)) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("KeyResult 20") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(1L, 40L)) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("KeyResult 40") + .build()); + static List alignmentSelectionOKR = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(5L, 21L)) + .withObjectiveTitle(alignmentObjectiveName) + .withKeyResultTitle("KeyResult 21") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(5L, 41L)) + .withObjectiveTitle(alignmentObjectiveName) + .withKeyResultTitle("KeyResult 41") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(5L, 61L)) + .withObjectiveTitle(alignmentObjectiveName) + .withKeyResultTitle("KeyResult 61") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(5L, 81L)) + .withObjectiveTitle(alignmentObjectiveName) + .withKeyResultTitle("KeyResult 81") + .build()); + static AlignmentSelection alignmentSelectionEmptyKeyResults = AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(8L, null)) + .withObjectiveTitle("Objective 8") + .build(); @Test void shouldGetAllObjectivesWithKeyResults() throws Exception { @@ -62,36 +88,49 @@ void shouldGetAllObjectivesWithKeyResults() throws Exception { alignmentSelections.addAll(alignmentSelectionPuzzle); alignmentSelections.addAll(alignmentSelectionOKR); alignmentSelections.add(alignmentSelectionEmptyKeyResults); - BDDMockito.given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(2L, 4L)) + BDDMockito + .given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(2L, 4L)) .willReturn(alignmentSelections); - mvc.perform(get("/api/v2/alignments/selections?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(3))) - .andExpect(jsonPath("$[0].id", Is.is(1))).andExpect(jsonPath("$[0].keyResults[0].id", Is.is(20))) - .andExpect(jsonPath("$[0].keyResults[1].id", Is.is(40))).andExpect(jsonPath("$[1].id", Is.is(5))) + mvc + .perform(get("/api/v2/alignments/selections?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(3))) + .andExpect(jsonPath("$[0].id", Is.is(1))) + .andExpect(jsonPath("$[0].keyResults[0].id", Is.is(20))) + .andExpect(jsonPath("$[0].keyResults[1].id", Is.is(40))) + .andExpect(jsonPath("$[1].id", Is.is(5))) .andExpect(jsonPath("$[1].keyResults[0].id", Is.is(21))) .andExpect(jsonPath("$[1].keyResults[1].id", Is.is(41))) .andExpect(jsonPath("$[1].keyResults[2].id", Is.is(61))) - .andExpect(jsonPath("$[1].keyResults[3].id", Is.is(81))).andExpect(jsonPath("$[2].id", Is.is(8))) + .andExpect(jsonPath("$[1].keyResults[3].id", Is.is(81))) + .andExpect(jsonPath("$[2].id", Is.is(8))) .andExpect(jsonPath("$[2].keyResults.size()", Is.is(0))); } @Test void shouldGetAllObjectivesWithKeyResultsIfAllObjectivesFiltered() throws Exception { - BDDMockito.given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(any(), any())) + BDDMockito + .given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(any(), any())) .willReturn(Collections.emptyList()); - mvc.perform(get("/api/v2/alignments/selections").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0))); + mvc + .perform(get("/api/v2/alignments/selections").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(0))); } @Test void shouldReturnObjectiveWithEmptyKeyResultListWhenNoKeyResultsInFilteredQuarter() throws Exception { - BDDMockito.given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(2L, 4L)) + BDDMockito + .given(alignmentSelectionBusinessService.getAlignmentSelectionByQuarterIdAndTeamIdNot(2L, 4L)) .willReturn(List.of(alignmentSelectionEmptyKeyResults)); - mvc.perform(get("/api/v2/alignments/selections?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(1))) - .andExpect(jsonPath("$[0].id", Is.is(8))).andExpect(jsonPath("$[0].keyResults.size()", Is.is(0))); + mvc + .perform(get("/api/v2/alignments/selections?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(1))) + .andExpect(jsonPath("$[0].id", Is.is(8))) + .andExpect(jsonPath("$[0].keyResults.size()", Is.is(0))); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/CacheControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/CacheControllerIT.java index 6fbe6bc0be..1c23c80fc9 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/CacheControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/CacheControllerIT.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.controller; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; + import ch.puzzle.okr.service.CacheService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -12,10 +16,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(CacheController.class) @@ -27,15 +27,17 @@ class CacheControllerIT { @Test void shouldEmptyAuthorisationUsersCache() throws Exception { - mvc.perform( - post("/api/v2/caches/emptyAuthorizationUsersCache").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post("/api/v2/caches/emptyAuthorizationUsersCache") + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()); verify(cacheService, times(1)).emptyAuthorizationUsersCache(); } @Test void shouldEmptyAllCaches() throws Exception { - mvc.perform(post("/api/v2/caches/emptyAllCaches").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post("/api/v2/caches/emptyAllCaches").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()); verify(cacheService, times(1)).emptyAllCaches(); } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/CheckInControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/CheckInControllerIT.java index 04201bca78..a662071aeb 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/CheckInControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/CheckInControllerIT.java @@ -1,13 +1,20 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.test.CheckInTestHelpers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.deserializer.DeserializerHelper; import ch.puzzle.okr.mapper.checkin.CheckInMapper; import ch.puzzle.okr.models.checkin.Zone; +import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; -import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.service.authorization.CheckInAuthorizationService; import ch.puzzle.okr.service.business.KeyResultBusinessService; +import java.time.LocalDateTime; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -27,14 +34,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; - -import static ch.puzzle.okr.test.CheckInTestHelpers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(CheckInController.class) @@ -60,8 +59,10 @@ void setUp() { void shouldGetMetricCheckInWithId() throws Exception { BDDMockito.given(checkInAuthorizationService.getEntityById(anyLong())).willReturn(checkInMetric); - mvc.perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_INITIATIVES, Is.is(INITIATIVES_1))) .andExpect(jsonPath(JSON_PATH_CONFIDENCE, Is.is(6))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_ID, Is.is(1))) @@ -74,8 +75,10 @@ void shouldGetMetricCheckInWithId() throws Exception { void shouldGetOrdinalCheckInWithId() throws Exception { BDDMockito.given(checkInAuthorizationService.getEntityById(anyLong())).willReturn(checkInOrdinal); - mvc.perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_ID, Is.is(4))) + mvc + .perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(4))) .andExpect(jsonPath(JSON_PATH_INITIATIVES, Is.is(INITIATIVES_2))) .andExpect(jsonPath(JSON_PATH_CONFIDENCE, Is.is(5))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_ID, Is.is(2))) @@ -86,23 +89,30 @@ void shouldGetOrdinalCheckInWithId() throws Exception { @Test void shouldNotFindTheCheckInWithId() throws Exception { - BDDMockito.given(checkInAuthorizationService.getEntityById(anyLong())) + BDDMockito + .given(checkInAuthorizationService.getEntityById(anyLong())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)); - mvc.perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnUpdatedCheckIn() throws Exception { - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultMetric.Builder.builder().withId(1L).build()); BDDMockito.given(checkInAuthorizationService.updateEntity(anyLong(), any())).willReturn(checkInMetric); BDDMockito.given(checkInMapper.toCheckIn(any())).willReturn(checkInMetric); - mvc.perform(put(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(put(CHECK_IN_5_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_CHANGE_INFO, Is.is(CHANGE_INFO_1))) .andExpect(jsonPath(JSON_PATH_INITIATIVES, Is.is(INITIATIVES_1))) .andExpect(jsonPath(JSON_PATH_CONFIDENCE, Is.is(6))) @@ -111,26 +121,36 @@ void shouldReturnUpdatedCheckIn() throws Exception { @Test void shouldReturnNotFound() throws Exception { - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultMetric.Builder.builder().withId(1L).build()); BDDMockito.given(checkInMapper.toCheckIn(any())).willReturn(checkInMetric); - BDDMockito.given(checkInAuthorizationService.updateEntity(anyLong(), any())) + BDDMockito + .given(checkInAuthorizationService.updateEntity(anyLong(), any())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found")); - mvc.perform(put(CHECK_IN_5_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) + mvc + .perform(put(CHECK_IN_5_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldCreateKeyResultMetric() throws Exception { - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultMetric.Builder.builder().withId(1L).build()); BDDMockito.given(checkInAuthorizationService.createEntity(any())).willReturn(checkInMetric); - mvc.perform(post(CHECK_IN_BASE_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(post(CHECK_IN_BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_CHANGE_INFO, Is.is(CHANGE_INFO_1))) .andExpect(jsonPath(JSON_PATH_INITIATIVES, Is.is(INITIATIVES_1))) .andExpect(jsonPath(JSON_PATH_CONFIDENCE, Is.is(6))) @@ -140,13 +160,18 @@ void shouldCreateKeyResultMetric() throws Exception { @Test void shouldCreateKeyResultOrdinal() throws Exception { - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultOrdinal.Builder.builder().withId(1L).build()); BDDMockito.given(checkInAuthorizationService.createEntity(any())).willReturn(checkInOrdinal); - mvc.perform(post(CHECK_IN_BASE_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(4))) + mvc + .perform(post(CHECK_IN_BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(4))) .andExpect(jsonPath(JSON_PATH_CHANGE_INFO, Is.is(CHANGE_INFO_2))) .andExpect(jsonPath(JSON_PATH_INITIATIVES, Is.is(INITIATIVES_2))) .andExpect(jsonPath(JSON_PATH_CONFIDENCE, Is.is(5))) @@ -156,12 +181,16 @@ void shouldCreateKeyResultOrdinal() throws Exception { @Test void shouldThrowExceptionWhenKeyResultIdMissing() throws Exception { - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultMetric.Builder.builder().withId(1L).build()); BDDMockito.given(checkInAuthorizationService.createEntity(any())).willReturn(checkInOrdinal); - mvc.perform(post(CHECK_IN_BASE_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON_WITHOUT_KEY_RESULT_ID)) + mvc + .perform(post(CHECK_IN_BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON_WITHOUT_KEY_RESULT_ID)) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @@ -171,17 +200,22 @@ void shouldReturnClientErrorForKeyResultNotOfTypeMetricOrOrdinal() throws Except class NonMetricOrOrdinalKeyResult extends KeyResult { } - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(new NonMetricOrOrdinalKeyResult()); - mvc.perform(post(CHECK_IN_BASE_URL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) + mvc + .perform(post(CHECK_IN_BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @Test void shouldDeleteCheckInById() throws Exception { - mvc.perform(delete(CHECK_IN_5_URL).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(CHECK_IN_5_URL).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/ClientConfigControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/ClientConfigControllerIT.java index f60eb9ede4..e538605b3b 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/ClientConfigControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/ClientConfigControllerIT.java @@ -1,7 +1,13 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.controller.OverviewControllerIT.JSON_PATH_ROOT; +import static org.mockito.ArgumentMatchers.anyString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.dto.ClientConfigDto; import ch.puzzle.okr.service.clientconfig.ClientConfigService; +import java.util.Map; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -15,13 +21,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.util.Map; - -import static ch.puzzle.okr.controller.OverviewControllerIT.JSON_PATH_ROOT; -import static org.mockito.ArgumentMatchers.anyString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(ClientConfigController.class) @@ -36,7 +35,8 @@ public class ClientConfigControllerIT { void shouldGetClientConfig() throws Exception { BDDMockito.given(configService.getConfigBasedOnActiveEnv(anyString())).willReturn(createClientConfigDto()); - mvc.perform(get("/config").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/config").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath(JSON_PATH_ROOT, Matchers.aMapWithSize(10))) .andExpect(jsonPath("$.activeProfile", Matchers.is("Active_Profile"))) @@ -54,8 +54,16 @@ void shouldGetClientConfig() throws Exception { private ClientConfigDto createClientConfigDto() { Map customStyles = Map.of("font-family", "verdana", "font-size", "20px"); - return new ClientConfigDto("Active_Profile", "Issuer", "Client_Id", "Favicon", "Logo", "Triangles", - "Background_Logo", "Title", "helpSiteUrl", customStyles); + return new ClientConfigDto("Active_Profile", + "Issuer", + "Client_Id", + "Favicon", + "Logo", + "Triangles", + "Background_Logo", + "Title", + "helpSiteUrl", + customStyles); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/CompletedControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/CompletedControllerIT.java index 4f2c00353c..9732dcb64e 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/CompletedControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/CompletedControllerIT.java @@ -1,5 +1,13 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.test.KeyResultTestHelpers.JSON_PATH_ID; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.dto.CompletedDto; import ch.puzzle.okr.mapper.CompletedMapper; import ch.puzzle.okr.models.Completed; @@ -25,14 +33,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import static ch.puzzle.okr.test.KeyResultTestHelpers.JSON_PATH_ID; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(CompletedController.class) @@ -56,18 +56,22 @@ class CompletedControllerIT { @MockBean private CompletedMapper completedMapper; - private final Completed successfulCompleted = Completed.Builder.builder() // + private final Completed successfulCompleted = Completed.Builder + .builder() // .withId(COMPLETED_ID) // - .withObjective(Objective.Builder.builder() // + .withObjective(Objective.Builder + .builder() // .withId(OBJECTIVE_ID) // .build()) // .withComment(COMPLETED_COMMENT) // .build(); - private final CompletedDto completedDto = CompletedDtoBuilder.builder() // + private final CompletedDto completedDto = CompletedDtoBuilder + .builder() // .withId(COMPLETED_ID) // .withComment(COMPLETED_COMMENT) // - .withObjectiveDto(ObjectiveDtoBuilder.builder() // + .withObjectiveDto(ObjectiveDtoBuilder + .builder() // .withId(OBJECTIVE_ID) // .build()) // .build(); @@ -87,10 +91,11 @@ void setUp() { void createShouldCreateCompleted() throws Exception { BDDMockito.given(this.completedAuthorizationService.createCompleted(any())).willReturn(successfulCompleted); - mvc.perform(post(baseUrl) // - .content(SUCCESSFUL_CREATE_BODY) // - .contentType(MediaType.APPLICATION_JSON) // - .with(SecurityMockMvcRequestPostProcessors.csrf())) // + mvc + .perform(post(baseUrl) // + .content(SUCCESSFUL_CREATE_BODY) // + .contentType(MediaType.APPLICATION_JSON) // + .with(SecurityMockMvcRequestPostProcessors.csrf())) // .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) // .andExpect(jsonPath(JSON_PATH_ID, Is.is(COMPLETED_ID_AS_INT))) // .andExpect(jsonPath("$.id", Is.is(COMPLETED_ID_AS_INT))) // @@ -101,7 +106,8 @@ void createShouldCreateCompleted() throws Exception { @DisplayName("delete() should delete Completed") @Test void deleteShouldDeleteCompleted() throws Exception { - mvc.perform(delete("/api/v2/completed/1").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v2/completed/1").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @@ -109,9 +115,11 @@ void deleteShouldDeleteCompleted() throws Exception { @Test void deleteShouldThrowExceptionWhenCompletedWithIdCantBeFound() throws Exception { doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Completed not found")) - .when(completedAuthorizationService).deleteCompletedByObjectiveId(anyLong()); + .when(completedAuthorizationService) + .deleteCompletedByObjectiveId(anyLong()); - mvc.perform(delete("/api/v2/completed/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v2/completed/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/KeyResultControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/KeyResultControllerIT.java index dbf4ed5d04..b6d333745e 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/KeyResultControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/KeyResultControllerIT.java @@ -1,5 +1,15 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; +import static ch.puzzle.okr.test.KeyResultTestHelpers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import ch.puzzle.okr.deserializer.DeserializerHelper; import ch.puzzle.okr.mapper.ActionMapper; import ch.puzzle.okr.mapper.checkin.CheckInMapper; @@ -12,6 +22,9 @@ import ch.puzzle.okr.service.business.KeyResultBusinessService; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.service.persistence.UserPersistenceService; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; @@ -31,20 +44,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; -import static ch.puzzle.okr.test.KeyResultTestHelpers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(KeyResultController.class) @@ -82,8 +81,10 @@ void shouldGetMetricKeyResultWithId() throws Exception { BDDMockito.given(keyResultAuthorizationService.getEntityById(anyLong())).willReturn(metricKeyResult); BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultMetricDto); - mvc.perform(get(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(get(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_OBJECTIVE_ID, Is.is(1))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_METRIC))) @@ -102,8 +103,10 @@ void shouldGetOrdinalKeyResultWithId() throws Exception { BDDMockito.given(keyResultAuthorizationService.getEntityById(anyLong())).willReturn(ordinalKeyResult); BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultOrdinalDto); - mvc.perform(get(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(get(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_ORDINAL))) .andExpect(jsonPath(JSON_PATH_OWNER_FIRSTNAME, Is.is(FIRSTNAME))) @@ -120,11 +123,14 @@ void shouldGetOrdinalKeyResultWithId() throws Exception { @Test void shouldNotFindTheKeyResultWithGivenId() throws Exception { - BDDMockito.given(keyResultAuthorizationService.getEntityById(anyLong())) + BDDMockito + .given(keyResultAuthorizationService.getEntityById(anyLong())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "KeyResult with id 55 not found")); - mvc.perform(get(URL_TO_KEY_RESULT_55).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isNotFound()).andExpect(status().isNotFound()); + mvc + .perform(get(URL_TO_KEY_RESULT_55).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect(status().isNotFound()); } @Test @@ -134,33 +140,44 @@ void shouldReturnCheckInsFromKeyResult() throws Exception { BDDMockito.given(checkInMapper.toDto(checkIn1)).willReturn(checkInDto1); BDDMockito.given(checkInMapper.toDto(checkIn2)).willReturn(checkInDto2); - mvc.perform(get(URL_TO_KEY_RESULT_5_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(2))) - .andExpect(jsonPath("$[0].id", Is.is(1))).andExpect(jsonPath("$[0].value", Is.is(23.0))) + mvc + .perform(get(URL_TO_KEY_RESULT_5_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(2))) + .andExpect(jsonPath("$[0].id", Is.is(1))) + .andExpect(jsonPath("$[0].value", Is.is(23.0))) .andExpect(jsonPath("$[0].keyResultId", Is.is(5))) .andExpect(jsonPath("$[0].changeInfo", Is.is("Changeinfo1"))) - .andExpect(jsonPath("$[0].initiatives", Is.is("Initiatives1"))).andExpect(jsonPath("$[1].id", Is.is(4))) - .andExpect(jsonPath("$[1].value", Is.is(12.0))).andExpect(jsonPath("$[1].keyResultId", Is.is(5))) + .andExpect(jsonPath("$[0].initiatives", Is.is("Initiatives1"))) + .andExpect(jsonPath("$[1].id", Is.is(4))) + .andExpect(jsonPath("$[1].value", Is.is(12.0))) + .andExpect(jsonPath("$[1].keyResultId", Is.is(5))) .andExpect(jsonPath("$[1].changeInfo", Is.is("Changeinfo2"))) .andExpect(jsonPath("$[1].initiatives", Is.is("Initiatives2"))); } @Test void shouldGetAllCheckInsIfNoCheckInExistsInKeyResult() throws Exception { - BDDMockito.given(keyResultAuthorizationService.getAllCheckInsByKeyResult(anyLong())) + BDDMockito + .given(keyResultAuthorizationService.getAllCheckInsByKeyResult(anyLong())) .willReturn(Collections.emptyList()); - mvc.perform(get(URL_TO_KEY_RESULT_1_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0))); + mvc + .perform(get(URL_TO_KEY_RESULT_1_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(0))); } @Test void shouldReturnErrorWhenKeyResultDoesntExistWhenGettingCheckInsFromKeyResult() throws Exception { - BDDMockito.given(keyResultAuthorizationService.getAllCheckInsByKeyResult(anyLong())) + BDDMockito + .given(keyResultAuthorizationService.getAllCheckInsByKeyResult(anyLong())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "KeyResult with id 1 not found")); - mvc.perform(get(URL_TO_KEY_RESULT_1_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isNotFound()).andExpect(status().isNotFound()); + mvc + .perform(get(URL_TO_KEY_RESULT_1_CHECK_IN).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isNotFound()) + .andExpect(status().isNotFound()); } @Test @@ -169,9 +186,13 @@ void createMetricKeyResult() throws Exception { BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultMetricDto); BDDMockito.given(keyResultMapper.toKeyResult(any())).willReturn(metricKeyResult); - mvc.perform(post(URL_BASE).content(CREATE_BODY_METRIC).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_METRIC) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_UNIT, Is.is(KEY_RESULT_UNIT.toString()))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_METRIC))) @@ -194,9 +215,13 @@ void createOrdinalKeyResult() throws Exception { BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultOrdinalDto); BDDMockito.given(keyResultMapper.toKeyResult(any())).willReturn(ordinalKeyResult); - mvc.perform(post(URL_BASE).content(CREATE_BODY_ORDINAL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_ORDINAL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_COMMIT_ZONE, Is.is(COMMIT_ZONE))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_ORDINAL))) @@ -214,10 +239,22 @@ void createOrdinalKeyResult() throws Exception { @Test void shouldCreateActionsWhenCreatingKeyResult() throws Exception { - Action action1 = Action.Builder.builder().withVersion(1).withAction("Neue Katze").withPriority(0) - .withKeyResult(ordinalKeyResult).withIsChecked(false).build(); - Action action2 = Action.Builder.builder().withVersion(1).withAction("Neuer Hund").withPriority(1) - .withKeyResult(ordinalKeyResult).withIsChecked(false).build(); + Action action1 = Action.Builder + .builder() + .withVersion(1) + .withAction("Neue Katze") + .withPriority(0) + .withKeyResult(ordinalKeyResult) + .withIsChecked(false) + .build(); + Action action2 = Action.Builder + .builder() + .withVersion(1) + .withAction("Neuer Hund") + .withPriority(1) + .withKeyResult(ordinalKeyResult) + .withIsChecked(false) + .build(); action1.setWriteable(false); action2.setWriteable(false); List actionList = List.of(action1, action2); @@ -227,9 +264,13 @@ void shouldCreateActionsWhenCreatingKeyResult() throws Exception { BDDMockito.given(actionAuthorizationService.createEntities(actionList)).willReturn(actionList); BDDMockito.given(actionMapper.toActions(anyList(), any())).willReturn(actionList); - mvc.perform(post(URL_BASE).content(CREATE_BODY_ORDINAL_ACTION_LIST).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_ORDINAL_ACTION_LIST) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_COMMIT_ZONE, Is.is(COMMIT_ZONE))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_ORDINAL))) @@ -247,15 +288,21 @@ void shouldCreateActionsWhenCreatingKeyResult() throws Exception { @Test void shouldThrowExceptionWhenKeyResultTypeMissing() throws Exception { - mvc.perform(post(URL_BASE).content(CREATE_BODY_KEY_RESULT_TYPE_MISSING).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_KEY_RESULT_TYPE_MISSING) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @Test void shouldThrowExceptionWhenKeyResultTypeUnknown() throws Exception { - mvc.perform(post(URL_BASE).content(CREATE_BODY_KEY_RESULT_TYPE_UNKNOWN).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_KEY_RESULT_TYPE_UNKNOWN) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @@ -265,9 +312,13 @@ void createEntityWithEnumKeys() throws Exception { BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultOrdinalDto); BDDMockito.given(keyResultMapper.toKeyResult(any())).willReturn(ordinalKeyResult); - mvc.perform(post(URL_BASE).content(CREATE_BODY_WITH_ENUM_KEYS).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()).andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_WITH_ENUM_KEYS) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andExpect(jsonPath(JSON_PATH_ID, Is.is(5))) .andExpect(jsonPath(JSON_PATH_OBJECTIVE_ID, Is.is(OBJECTIVE_ID))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, Is.is(DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_ORDINAL))) @@ -282,32 +333,44 @@ void createEntityWithEnumKeys() throws Exception { @Test void createEntityShouldThrowErrorWhenInvalidDto() throws Exception { - BDDMockito.given(keyResultMapper.toKeyResult(any())) + BDDMockito + .given(keyResultMapper.toKeyResult(any())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Error")); - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultOrdinal.Builder.builder().withId(1L).build()); - mvc.perform(post(URL_BASE).content(CREATE_BODY_ORDINAL).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post(URL_BASE) + .content(CREATE_BODY_ORDINAL) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnUpdatedKeyResult() throws Exception { - BDDMockito.given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) + BDDMockito + .given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) .willReturn(new KeyResultWithActionList(metricKeyResult, List.of())); BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultMetricDto); BDDMockito.given(keyResultMapper.toKeyResult(any())).willReturn(metricKeyResult); BDDMockito.given(keyResultAuthorizationService.isImUsed(any(), any())).willReturn(false); - BDDMockito.given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) + BDDMockito + .given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) .willReturn(new KeyResultWithActionList(metricKeyResult, List.of())); - BDDMockito.given(keyResultBusinessService.getEntityById(anyLong())) + BDDMockito + .given(keyResultBusinessService.getEntityById(anyLong())) .willReturn(KeyResultMetric.Builder.builder().withId(1L).build()); - mvc.perform(put(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath(JSON_PATH_TITLE, Is.is(TITLE))) + mvc + .perform(put(URL_TO_KEY_RESULT_1) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath(JSON_PATH_TITLE, Is.is(TITLE))) .andExpect(jsonPath(JSON_PATH_OWNER_FIRSTNAME, Is.is(FIRSTNAME))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_METRIC))) .andExpect(jsonPath(JSON_PATH_BASELINE, Is.is(BASELINE_VALUE))) @@ -315,7 +378,8 @@ void shouldReturnUpdatedKeyResult() throws Exception { .andExpect(jsonPath(JSON_PATH_OBJECTIVE_ID, Is.is(OBJECTIVE_ID))) .andExpect(jsonPath(JSON_PATH_LAST_CHECK_IN_ID, Is.is(LAST_CHECK_IN_ID))) .andExpect(jsonPath(JSON_PATH_LAST_CHECK_IN_CONFIDENCE, Is.is(CONFIDENCE))) - .andExpect(jsonPath(JSON_PATH_UNIT, Is.is(KEY_RESULT_UNIT.toString()))).andReturn(); + .andExpect(jsonPath(JSON_PATH_UNIT, Is.is(KEY_RESULT_UNIT.toString()))) + .andReturn(); verify(actionMapper, times(1)).toActions(anyList(), any()); verify(keyResultAuthorizationService, times(1)).updateEntities(anyLong(), any(), anyList()); @@ -323,15 +387,20 @@ void shouldReturnUpdatedKeyResult() throws Exception { @Test void shouldReturnUpdatedKeyResultWithImUsed() throws Exception { - BDDMockito.given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) + BDDMockito + .given(keyResultAuthorizationService.updateEntities(anyLong(), any(), anyList())) .willReturn(new KeyResultWithActionList(metricKeyResult, List.of())); BDDMockito.given(keyResultMapper.toDto(any(), anyList())).willReturn(keyResultMetricDto); BDDMockito.given(keyResultMapper.toKeyResult(any())).willReturn(metricKeyResult); BDDMockito.given(keyResultAuthorizationService.isImUsed(any(), any())).willReturn(true); - mvc.perform(put(URL_TO_KEY_RESULT_1).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(JSON)) - .andExpect(MockMvcResultMatchers.status().isImUsed()).andExpect(jsonPath(JSON_PATH_TITLE, Is.is(TITLE))) + mvc + .perform(put(URL_TO_KEY_RESULT_1) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(JSON)) + .andExpect(MockMvcResultMatchers.status().isImUsed()) + .andExpect(jsonPath(JSON_PATH_TITLE, Is.is(TITLE))) .andExpect(jsonPath(JSON_PATH_OWNER_FIRSTNAME, Is.is(FIRSTNAME))) .andExpect(jsonPath(JSON_PATH_KEY_RESULT_TYPE, Is.is(KEY_RESULT_TYPE_METRIC))) .andExpect(jsonPath(JSON_PATH_BASELINE, Is.is(BASELINE_VALUE))) @@ -339,7 +408,8 @@ void shouldReturnUpdatedKeyResultWithImUsed() throws Exception { .andExpect(jsonPath(JSON_PATH_OBJECTIVE_ID, Is.is(OBJECTIVE_ID))) .andExpect(jsonPath(JSON_PATH_LAST_CHECK_IN_ID, Is.is(LAST_CHECK_IN_ID))) .andExpect(jsonPath(JSON_PATH_LAST_CHECK_IN_CONFIDENCE, Is.is(CONFIDENCE))) - .andExpect(jsonPath(JSON_PATH_UNIT, Is.is(KEY_RESULT_UNIT.toString()))).andReturn(); + .andExpect(jsonPath(JSON_PATH_UNIT, Is.is(KEY_RESULT_UNIT.toString()))) + .andReturn(); verify(actionMapper, times(1)).toActions(anyList(), any()); verify(keyResultAuthorizationService, times(1)).updateEntities(anyLong(), any(), anyList()); @@ -348,34 +418,43 @@ void shouldReturnUpdatedKeyResultWithImUsed() throws Exception { @Test void shouldReturnNotFoundWhenUpdatingKeyResult() throws Exception { doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Keyresult not found")) - .when(keyResultAuthorizationService).updateEntities(any(), any(), anyList()); - - mvc.perform(put(URL_TO_KEY_RESULT_1000).content(PUT_BODY_METRIC).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + .when(keyResultAuthorizationService) + .updateEntities(any(), any(), anyList()); + + mvc + .perform(put(URL_TO_KEY_RESULT_1000) + .content(PUT_BODY_METRIC) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnBadRequestWhenUpdatingKeyResult() throws Exception { - BDDMockito.given(keyResultAuthorizationService.updateEntity(any(), any())) + BDDMockito + .given(keyResultAuthorizationService.updateEntity(any(), any())) .willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Bad request while updating keyresult")); - mvc.perform(put(URL_TO_KEY_RESULT_10).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_TO_KEY_RESULT_10).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isBadRequest()); } @Test void shouldDeleteKeyResult() throws Exception { - mvc.perform(delete(URL_TO_KEY_RESULT_10).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(URL_TO_KEY_RESULT_10).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void throwExceptionWhenKeyResultWithIdCantBeFoundWhileDeleting() throws Exception { doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Keyresult not found")) - .when(keyResultAuthorizationService).deleteEntityById(anyLong()); + .when(keyResultAuthorizationService) + .deleteEntityById(anyLong()); - mvc.perform(delete(URL_TO_KEY_RESULT_1000).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(URL_TO_KEY_RESULT_1000).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/ObjectiveControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/ObjectiveControllerIT.java index 4a223397f8..eeb5df3003 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/ObjectiveControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/ObjectiveControllerIT.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.test.KeyResultTestHelpers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.deserializer.DeserializerHelper; import ch.puzzle.okr.dto.ObjectiveDto; import ch.puzzle.okr.mapper.ObjectiveMapper; @@ -10,6 +17,7 @@ import ch.puzzle.okr.service.authorization.ActionAuthorizationService; import ch.puzzle.okr.service.authorization.AuthorizationService; import ch.puzzle.okr.service.authorization.ObjectiveAuthorizationService; +import java.time.LocalDateTime; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -28,15 +36,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; - -import static ch.puzzle.okr.test.KeyResultTestHelpers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(ObjectiveController.class) @@ -80,21 +79,57 @@ class ObjectiveControllerIT { private static final String RESPONSE_NEW_OBJECTIVE = """ {"id":null,"version":1,"title":"Program Faster","teamId":1,"quarterId":1,"quarterLabel":"GJ 22/23-Q2","description":"Just be faster","state":"DRAFT","createdOn":null,"modifiedOn":null,"writeable":true}"""; private static final String JSON_PATH_TITLE = "$.title"; - private static final Objective objective1 = Objective.Builder.builder().withId(5L).withTitle(OBJECTIVE_TITLE_1) + private static final Objective objective1 = Objective.Builder + .builder() + .withId(5L) + .withTitle(OBJECTIVE_TITLE_1) .build(); - private static final Objective objective2 = Objective.Builder.builder().withId(7L).withTitle(OBJECTIVE_TITLE_2) + private static final Objective objective2 = Objective.Builder + .builder() + .withId(7L) + .withTitle(OBJECTIVE_TITLE_2) + .build(); + private static final User user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") .build(); - private static final User user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); private static final Team team = Team.Builder.builder().withId(1L).withName("Team1").build(); private static final Quarter quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build(); - private static final Objective fullObjective = Objective.Builder.builder().withId(42L).withTitle("FullObjective") - .withCreatedBy(user).withTeam(team).withQuarter(quarter).withDescription(DESCRIPTION) - .withModifiedOn(LocalDateTime.MAX).build(); - private static final ObjectiveDto objective1Dto = new ObjectiveDto(5L, 1, OBJECTIVE_TITLE_1, 1L, 1L, "GJ 22/23-Q2", - DESCRIPTION, State.DRAFT, LocalDateTime.MAX, LocalDateTime.MAX, true); - private static final ObjectiveDto objective2Dto = new ObjectiveDto(7L, 1, OBJECTIVE_TITLE_2, 1L, 1L, "GJ 22/23-Q2", - DESCRIPTION, State.DRAFT, LocalDateTime.MIN, LocalDateTime.MIN, true); + private static final Objective fullObjective = Objective.Builder + .builder() + .withId(42L) + .withTitle("FullObjective") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withDescription(DESCRIPTION) + .withModifiedOn(LocalDateTime.MAX) + .build(); + private static final ObjectiveDto objective1Dto = new ObjectiveDto(5L, + 1, + OBJECTIVE_TITLE_1, + 1L, + 1L, + "GJ 22/23-Q2", + DESCRIPTION, + State.DRAFT, + LocalDateTime.MAX, + LocalDateTime.MAX, + true); + private static final ObjectiveDto objective2Dto = new ObjectiveDto(7L, + 1, + OBJECTIVE_TITLE_2, + 1L, + 1L, + "GJ 22/23-Q2", + DESCRIPTION, + State.DRAFT, + LocalDateTime.MIN, + LocalDateTime.MIN, + true); @Autowired private MockMvc mvc; @@ -121,30 +156,46 @@ void setUp() { void getObjectiveById() throws Exception { BDDMockito.given(objectiveAuthorizationService.getEntityById(anyLong())).willReturn(objective1); - mvc.perform(get(URL_OBJECTIVE_5).contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$.id", Is.is(5))) + mvc + .perform(get(URL_OBJECTIVE_5).contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$.id", Is.is(5))) .andExpect(jsonPath(JSON_PATH_TITLE, Is.is(OBJECTIVE_TITLE_1))); } @Test void getObjectiveByIdFail() throws Exception { - BDDMockito.given(objectiveAuthorizationService.getEntityById(anyLong())) + BDDMockito + .given(objectiveAuthorizationService.getEntityById(anyLong())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)); - mvc.perform(get(URL_OBJECTIVE_10).contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get(URL_OBJECTIVE_10).contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnObjectiveWhenCreatingNewObjective() throws Exception { - ObjectiveDto testObjective = new ObjectiveDto(null, 1, "Program Faster", 1L, 1L, "GJ 22/23-Q2", - "Just be faster", State.DRAFT, null, null, true); + ObjectiveDto testObjective = new ObjectiveDto(null, + 1, + "Program Faster", + 1L, + 1L, + "GJ 22/23-Q2", + "Just be faster", + State.DRAFT, + null, + null, + true); BDDMockito.given(objectiveMapper.toDto(any())).willReturn(testObjective); BDDMockito.given(objectiveAuthorizationService.createEntity(any())).willReturn(fullObjective); - mvc.perform(post(URL_BASE_OBJECTIVE).contentType(MediaType.APPLICATION_JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf()).content(CREATE_NEW_OBJECTIVE)) + mvc + .perform(post(URL_BASE_OBJECTIVE) + .contentType(MediaType.APPLICATION_JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(CREATE_NEW_OBJECTIVE)) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) .andExpect(MockMvcResultMatchers.content().string(RESPONSE_NEW_OBJECTIVE)); verify(objectiveAuthorizationService, times(1)).createEntity(any()); @@ -152,27 +203,49 @@ void shouldReturnObjectiveWhenCreatingNewObjective() throws Exception { @Test void shouldReturnResponseStatusExceptionWhenCreatingObjectiveWithNullValues() throws Exception { - BDDMockito.given(objectiveAuthorizationService.createEntity(any())).willThrow( - new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing attribute title when creating objective")); - - mvc.perform(post(URL_BASE_OBJECTIVE).contentType(MediaType.APPLICATION_JSON) - .content(CREATE_NEW_OBJECTIVE_WITH_NULL_VALUES).with(SecurityMockMvcRequestPostProcessors.csrf())) + BDDMockito + .given(objectiveAuthorizationService.createEntity(any())) + .willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Missing attribute title when creating objective")); + + mvc + .perform(post(URL_BASE_OBJECTIVE) + .contentType(MediaType.APPLICATION_JSON) + .content(CREATE_NEW_OBJECTIVE_WITH_NULL_VALUES) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isBadRequest()); } @Test void shouldReturnUpdatedObjective() throws Exception { - ObjectiveDto testObjective = new ObjectiveDto(1L, 1, TITLE, 1L, 1L, "GJ 22/23-Q2", EVERYTHING_FINE_DESCRIPTION, - State.NOTSUCCESSFUL, LocalDateTime.MIN, LocalDateTime.MAX, true); - Objective objective = Objective.Builder.builder().withId(1L).withDescription(EVERYTHING_FINE_DESCRIPTION) - .withTitle(TITLE).build(); + ObjectiveDto testObjective = new ObjectiveDto(1L, + 1, + TITLE, + 1L, + 1L, + "GJ 22/23-Q2", + EVERYTHING_FINE_DESCRIPTION, + State.NOTSUCCESSFUL, + LocalDateTime.MIN, + LocalDateTime.MAX, + true); + Objective objective = Objective.Builder + .builder() + .withId(1L) + .withDescription(EVERYTHING_FINE_DESCRIPTION) + .withTitle(TITLE) + .build(); BDDMockito.given(objectiveMapper.toDto(any())).willReturn(testObjective); BDDMockito.given(objectiveAuthorizationService.updateEntity(anyLong(), any())).willReturn(objective); BDDMockito.given(objectiveAuthorizationService.isImUsed(any())).willReturn(false); - mvc.perform(put(URL_OBJECTIVE_10).contentType(MediaType.APPLICATION_JSON).content(JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())).andExpect(MockMvcResultMatchers.status().isOk()) + mvc + .perform(put(URL_OBJECTIVE_10) + .contentType(MediaType.APPLICATION_JSON) + .content(JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath("$.id", Is.is(1))) .andExpect(jsonPath("$.description", Is.is(EVERYTHING_FINE_DESCRIPTION))) .andExpect(jsonPath(JSON_PATH_TITLE, Is.is(TITLE))); @@ -180,10 +253,23 @@ void shouldReturnUpdatedObjective() throws Exception { @Test void shouldReturnImUsed() throws Exception { - ObjectiveDto testObjectiveDto = new ObjectiveDto(1L, 1, TITLE, 1L, 1L, "GJ 22/23-Q2", - EVERYTHING_FINE_DESCRIPTION, State.SUCCESSFUL, LocalDateTime.MAX, LocalDateTime.MAX, true); - Objective objectiveImUsed = Objective.Builder.builder().withId(1L).withDescription(EVERYTHING_FINE_DESCRIPTION) - .withQuarter(Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build()).withTitle(TITLE) + ObjectiveDto testObjectiveDto = new ObjectiveDto(1L, + 1, + TITLE, + 1L, + 1L, + "GJ 22/23-Q2", + EVERYTHING_FINE_DESCRIPTION, + State.SUCCESSFUL, + LocalDateTime.MAX, + LocalDateTime.MAX, + true); + Objective objectiveImUsed = Objective.Builder + .builder() + .withId(1L) + .withDescription(EVERYTHING_FINE_DESCRIPTION) + .withQuarter(Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build()) + .withTitle(TITLE) .build(); BDDMockito.given(objectiveMapper.toObjective(any())).willReturn(objectiveImUsed); @@ -191,56 +277,74 @@ void shouldReturnImUsed() throws Exception { BDDMockito.given(objectiveAuthorizationService.updateEntity(anyLong(), any())).willReturn(objectiveImUsed); BDDMockito.given(objectiveAuthorizationService.isImUsed(any())).willReturn(true); - mvc.perform(put(URL_OBJECTIVE_10).contentType(MediaType.APPLICATION_JSON).content(JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_OBJECTIVE_10) + .contentType(MediaType.APPLICATION_JSON) + .content(JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isImUsed()); } @Test void shouldReturnNotFound() throws Exception { - BDDMockito.given(objectiveAuthorizationService.updateEntity(anyLong(), any())).willThrow( - new ResponseStatusException(HttpStatus.NOT_FOUND, "Failed objective -> Attribut is invalid")); - - mvc.perform(put(URL_OBJECTIVE_10).contentType(MediaType.APPLICATION_JSON).content(JSON) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + BDDMockito + .given(objectiveAuthorizationService.updateEntity(anyLong(), any())) + .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, + "Failed objective -> Attribut is invalid")); + + mvc + .perform(put(URL_OBJECTIVE_10) + .contentType(MediaType.APPLICATION_JSON) + .content(JSON) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnBadRequest() throws Exception { - BDDMockito.given(objectiveAuthorizationService.updateEntity(anyLong(), any())).willThrow( - new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed objective -> Attribut is invalid")); + BDDMockito + .given(objectiveAuthorizationService.updateEntity(anyLong(), any())) + .willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Failed objective -> Attribut is invalid")); - mvc.perform(put(URL_OBJECTIVE_10).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_OBJECTIVE_10).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isBadRequest()); } @Test void shouldDeleteObjective() throws Exception { - mvc.perform(delete(URL_OBJECTIVE_10).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(URL_OBJECTIVE_10).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void throwExceptionWhenObjectiveWithIdCantBeFoundWhileDeleting() throws Exception { doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Objective not found")) - .when(objectiveAuthorizationService).deleteEntityById(anyLong()); + .when(objectiveAuthorizationService) + .deleteEntityById(anyLong()); - mvc.perform(delete("/api/v2/objectives/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v2/objectives/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnIsCreatedWhenObjectiveWasDuplicated() throws Exception { - BDDMockito.given(objectiveAuthorizationService.duplicateEntity(anyLong(), any(), anyList())) + BDDMockito + .given(objectiveAuthorizationService.duplicateEntity(anyLong(), any(), anyList())) .willReturn(objective1); BDDMockito.given(keyResultMapper.toDto(any(KeyResultMetric.class), any())).willReturn(keyResultMetricDto); BDDMockito.given(keyResultMapper.toDto(any(KeyResultOrdinal.class), any())).willReturn(keyResultOrdinalDto); BDDMockito.given(objectiveAuthorizationService.getAuthorizationService()).willReturn(authorizationService); BDDMockito.given(objectiveMapper.toDto(objective1)).willReturn(objective1Dto); - mvc.perform(post(URL_DUPLICATE_OBJECTIVE_5).with(SecurityMockMvcRequestPostProcessors.csrf()) - .content(DUPLICATE_OBJECTIVE).contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(post(URL_DUPLICATE_OBJECTIVE_5) + .with(SecurityMockMvcRequestPostProcessors.csrf()) + .content(DUPLICATE_OBJECTIVE) + .contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.id", Is.is(objective1Dto.id().intValue()))) .andExpect(jsonPath("$.description", Is.is(objective1Dto.description()))) .andExpect(jsonPath(JSON_PATH_TITLE, Is.is(objective1Dto.title()))); diff --git a/backend/src/test/java/ch/puzzle/okr/controller/OverviewControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/OverviewControllerIT.java index 48b57a8ede..5e6dc0b997 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/OverviewControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/OverviewControllerIT.java @@ -1,9 +1,20 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.models.State.DRAFT; +import static ch.puzzle.okr.models.State.ONGOING; +import static org.mockito.ArgumentMatchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.mapper.OverviewMapper; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.models.overview.OverviewId; import ch.puzzle.okr.service.authorization.OverviewAuthorizationService; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.Test; @@ -19,18 +30,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.models.State.DRAFT; -import static ch.puzzle.okr.models.State.ONGOING; -import static org.mockito.ArgumentMatchers.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(OverviewController.class) @@ -54,37 +53,100 @@ class OverviewControllerIT { public static final String JSON_PATH_TEAM_ID = "$[0].team.id"; public static final String JSON_PATH_ROOT = "$"; - static List overviewPuzzle = List.of( - Overview.Builder.builder().withOverviewId(OverviewId.of(1L, 1L, 20L, 20L)).withTeamName(PUZZLE) - .withObjectiveTitle("Objective 1").withObjectiveState(DRAFT).withQuarterId(1L) - .withQuarterLabel(QUARTER_LABEL).withKeyResultTitle(DESCRIPTION) - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withUnit(CHF).withBaseline(5.0).withStretchGoal(20.0) - .withCheckInValue(15.0).withConfidence(5).withCheckInCreatedOn(LocalDateTime.now()).build(), - Overview.Builder.builder().withOverviewId(OverviewId.of(1L, 2L, 21L, 41L)).withTeamName(PUZZLE) - .withObjectiveTitle("Objective 1").withObjectiveState(DRAFT).withQuarterId(1L) - .withQuarterLabel(QUARTER_LABEL).withKeyResultTitle(DESCRIPTION) - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withUnit(EUR).withBaseline(5.0).withStretchGoal(20.0) - .withCheckInValue(15.0).withConfidence(5).withCheckInCreatedOn(LocalDateTime.now()).build()); - static List overviewOKR = List.of( - Overview.Builder.builder().withOverviewId(OverviewId.of(2L, 5L, 20L, 40L)).withTeamName("OKR") - .withObjectiveTitle("Objective 5").withObjectiveState(DRAFT).withQuarterId(1L) - .withQuarterLabel(QUARTER_LABEL).withKeyResultTitle(DESCRIPTION) - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withUnit(CHF).withBaseline(5.0).withStretchGoal(20.0) - .withCheckInValue(15.0).withConfidence(5).withCheckInCreatedOn(LocalDateTime.now()).build(), - Overview.Builder.builder().withOverviewId(OverviewId.of(2L, 7L, 21L, 41L)).withTeamName("OKR") - .withObjectiveTitle("Objective 7").withObjectiveState(ONGOING).withQuarterId(1L) - .withQuarterLabel(QUARTER_LABEL).withKeyResultTitle(DESCRIPTION) - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withUnit(FTE).withBaseline(5.0).withStretchGoal(20.0) - .withCheckInValue(15.0).withConfidence(5).withCheckInCreatedOn(LocalDateTime.now()).build()); - - static Overview overviewKuchen = Overview.Builder.builder().withOverviewId(OverviewId.of(3L, 8L, 20L, 40L)) - .withTeamName(TEAM_KUCHEN).withObjectiveTitle("Objective 8").withObjectiveState(ONGOING).withQuarterId(1L) - .withQuarterLabel(QUARTER_LABEL).withKeyResultTitle(DESCRIPTION).withKeyResultType(KEY_RESULT_TYPE_METRIC) - .withUnit(EUR).withBaseline(5.0).withStretchGoal(20.0).withCheckInValue(15.0).withConfidence(5) - .withCheckInCreatedOn(LocalDateTime.now()).build(); - - static Overview simpleOverview = Overview.Builder.builder().withOverviewId(OverviewId.of(4L, -1L, -1L, -1L)) - .withTeamName(TEAM_KUCHEN).build(); + static List overviewPuzzle = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.of(1L, 1L, 20L, 20L)) + .withTeamName(PUZZLE) + .withObjectiveTitle("Objective 1") + .withObjectiveState(DRAFT) + .withQuarterId(1L) + .withQuarterLabel(QUARTER_LABEL) + .withKeyResultTitle(DESCRIPTION) + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withUnit(CHF) + .withBaseline(5.0) + .withStretchGoal(20.0) + .withCheckInValue(15.0) + .withConfidence(5) + .withCheckInCreatedOn(LocalDateTime.now()) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.of(1L, 2L, 21L, 41L)) + .withTeamName(PUZZLE) + .withObjectiveTitle("Objective 1") + .withObjectiveState(DRAFT) + .withQuarterId(1L) + .withQuarterLabel(QUARTER_LABEL) + .withKeyResultTitle(DESCRIPTION) + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withUnit(EUR) + .withBaseline(5.0) + .withStretchGoal(20.0) + .withCheckInValue(15.0) + .withConfidence(5) + .withCheckInCreatedOn(LocalDateTime.now()) + .build()); + static List overviewOKR = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.of(2L, 5L, 20L, 40L)) + .withTeamName("OKR") + .withObjectiveTitle("Objective 5") + .withObjectiveState(DRAFT) + .withQuarterId(1L) + .withQuarterLabel(QUARTER_LABEL) + .withKeyResultTitle(DESCRIPTION) + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withUnit(CHF) + .withBaseline(5.0) + .withStretchGoal(20.0) + .withCheckInValue(15.0) + .withConfidence(5) + .withCheckInCreatedOn(LocalDateTime.now()) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.of(2L, 7L, 21L, 41L)) + .withTeamName("OKR") + .withObjectiveTitle("Objective 7") + .withObjectiveState(ONGOING) + .withQuarterId(1L) + .withQuarterLabel(QUARTER_LABEL) + .withKeyResultTitle(DESCRIPTION) + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withUnit(FTE) + .withBaseline(5.0) + .withStretchGoal(20.0) + .withCheckInValue(15.0) + .withConfidence(5) + .withCheckInCreatedOn(LocalDateTime.now()) + .build()); + + static Overview overviewKuchen = Overview.Builder + .builder() + .withOverviewId(OverviewId.of(3L, 8L, 20L, 40L)) + .withTeamName(TEAM_KUCHEN) + .withObjectiveTitle("Objective 8") + .withObjectiveState(ONGOING) + .withQuarterId(1L) + .withQuarterLabel(QUARTER_LABEL) + .withKeyResultTitle(DESCRIPTION) + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withUnit(EUR) + .withBaseline(5.0) + .withStretchGoal(20.0) + .withCheckInValue(15.0) + .withConfidence(5) + .withCheckInCreatedOn(LocalDateTime.now()) + .build(); + + static Overview simpleOverview = Overview.Builder + .builder() + .withOverviewId(OverviewId.of(4L, -1L, -1L, -1L)) + .withTeamName(TEAM_KUCHEN) + .build(); @Test void shouldGetAllTeamsWithObjective() throws Exception { @@ -92,31 +154,37 @@ void shouldGetAllTeamsWithObjective() throws Exception { overviews.addAll(overviewPuzzle); overviews.addAll(overviewOKR); overviews.add(overviewKuchen); - BDDMockito.given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) + BDDMockito + .given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) .willReturn(overviews); BDDMockito.given(overviewAuthorizationService.hasWriteAllAccess()).willReturn(true); - mvc.perform(get("/api/v2/overview?quarter=2&team=1,2,3,4").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/api/v2/overview?quarter=2&team=1,2,3,4").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath(JSON_PATH_ROOT, Matchers.hasSize(3))) .andExpect(jsonPath(JSON_PATH_TEAM_ID, Is.is(1))) .andExpect(jsonPath(JSON_PATH_TEAM_NAME, Is.is(PUZZLE))) .andExpect(jsonPath("$[0].objectives[0].id", Is.is(1))) - .andExpect(jsonPath("$[0].objectives[1].id", Is.is(2))).andExpect(jsonPath("$[1].team.id", Is.is(2))) + .andExpect(jsonPath("$[0].objectives[1].id", Is.is(2))) + .andExpect(jsonPath("$[1].team.id", Is.is(2))) .andExpect(jsonPath("$[1].team.name", Is.is("OKR"))) .andExpect(jsonPath("$[1].objectives[0].id", Is.is(5))) - .andExpect(jsonPath("$[1].objectives[1].id", Is.is(7))).andExpect(jsonPath("$[2].team.id", Is.is(3))) + .andExpect(jsonPath("$[1].objectives[1].id", Is.is(7))) + .andExpect(jsonPath("$[2].team.id", Is.is(3))) .andExpect(jsonPath("$[2].team.name", Is.is(TEAM_KUCHEN))) .andExpect(jsonPath("$[2].objectives[0].id", Is.is(8))); } @Test void shouldGetAllTeamsWithObjectiveIfNoTeamsExists() throws Exception { - BDDMockito.given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) + BDDMockito + .given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) .willReturn(Collections.emptyList()); BDDMockito.given(overviewAuthorizationService.hasWriteAllAccess()).willReturn(true); - mvc.perform(get("/api/v2/overview").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/api/v2/overview").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath(JSON_PATH_ROOT, Matchers.hasSize(0))); } @@ -125,26 +193,31 @@ void shouldGetAllTeamsWithObjectiveIfNoTeamsExists() throws Exception { void shouldReturnOnlyFilteredObjectivesByQuarterAndTeam() throws Exception { List overviews = new ArrayList<>(overviewPuzzle); overviews.add(overviewKuchen); - BDDMockito.given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) + BDDMockito + .given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) .willReturn(overviews); - mvc.perform(get("/api/v2/overview?quarter=2&team=1,3").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/api/v2/overview?quarter=2&team=1,3").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath(JSON_PATH_ROOT, Matchers.hasSize(2))) .andExpect(jsonPath(JSON_PATH_TEAM_ID, Is.is(1))) .andExpect(jsonPath(JSON_PATH_TEAM_NAME, Is.is(PUZZLE))) .andExpect(jsonPath("$[0].objectives[0].id", Is.is(1))) - .andExpect(jsonPath("$[0].objectives[1].id", Is.is(2))).andExpect(jsonPath("$[1].team.id", Is.is(3))) + .andExpect(jsonPath("$[0].objectives[1].id", Is.is(2))) + .andExpect(jsonPath("$[1].team.id", Is.is(3))) .andExpect(jsonPath("$[1].team.name", Is.is(TEAM_KUCHEN))) .andExpect(jsonPath("$[1].objectives[0].id", Is.is(8))); } @Test void shouldReturnTeamWithEmptyObjectiveListWhenNoObjectiveInFilteredQuarter() throws Exception { - BDDMockito.given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) + BDDMockito + .given(overviewAuthorizationService.getFilteredOverview(anyLong(), anyList(), anyString())) .willReturn(List.of(simpleOverview)); - mvc.perform(get("/api/v2/overview?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/api/v2/overview?quarter=2&team=4").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath(JSON_PATH_ROOT, Matchers.hasSize(1))) .andExpect(jsonPath(JSON_PATH_TEAM_ID, Is.is(4))) diff --git a/backend/src/test/java/ch/puzzle/okr/controller/QuarterControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/QuarterControllerIT.java index 5a582cd117..28f7e95314 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/QuarterControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/QuarterControllerIT.java @@ -1,7 +1,16 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; +import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.service.business.QuarterBusinessService; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.Test; @@ -17,27 +26,32 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.time.LocalDate; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; -import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(QuarterController.class) class QuarterControllerIT { - static Quarter quarter1 = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2") - .withStartDate(LocalDate.of(2022, 9, 1)).withEndDate(LocalDate.of(2022, 12, 31)).build(); - static Quarter quarter2 = Quarter.Builder.builder().withId(2L).withLabel("GJ 22/23-Q3") - .withStartDate(LocalDate.of(2023, 1, 1)).withEndDate(LocalDate.of(2023, 3, 31)).build(); - static Quarter backlogQuarter = Quarter.Builder.builder().withId(BACK_LOG_QUARTER_ID) - .withLabel(BACK_LOG_QUARTER_LABEL).withStartDate(null).withEndDate(null).build(); + static Quarter quarter1 = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ 22/23-Q2") + .withStartDate(LocalDate.of(2022, 9, 1)) + .withEndDate(LocalDate.of(2022, 12, 31)) + .build(); + static Quarter quarter2 = Quarter.Builder + .builder() + .withId(2L) + .withLabel("GJ 22/23-Q3") + .withStartDate(LocalDate.of(2023, 1, 1)) + .withEndDate(LocalDate.of(2023, 3, 31)) + .build(); + static Quarter backlogQuarter = Quarter.Builder + .builder() + .withId(BACK_LOG_QUARTER_ID) + .withLabel(BACK_LOG_QUARTER_LABEL) + .withStartDate(null) + .withEndDate(null) + .build(); static List quaterList = Arrays.asList(quarter1, quarter2, backlogQuarter); @Autowired @@ -49,12 +63,16 @@ class QuarterControllerIT { void shouldGetAllQuarters() throws Exception { BDDMockito.given(quarterBusinessService.getQuarters()).willReturn(quaterList); - mvc.perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(3))) - .andExpect(jsonPath("$[0].id", Is.is(1))).andExpect(jsonPath("$[0].label", Is.is("GJ 22/23-Q2"))) + mvc + .perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(3))) + .andExpect(jsonPath("$[0].id", Is.is(1))) + .andExpect(jsonPath("$[0].label", Is.is("GJ 22/23-Q2"))) .andExpect(jsonPath("$[0].startDate", Is.is(LocalDate.of(2022, 9, 1).toString()))) .andExpect(jsonPath("$[0].endDate", Is.is(LocalDate.of(2022, 12, 31).toString()))) - .andExpect(jsonPath("$[1].id", Is.is(2))).andExpect(jsonPath("$[1].label", Is.is("GJ 22/23-Q3"))) + .andExpect(jsonPath("$[1].id", Is.is(2))) + .andExpect(jsonPath("$[1].label", Is.is("GJ 22/23-Q3"))) .andExpect(jsonPath("$[1].startDate", Is.is(LocalDate.of(2023, 1, 1).toString()))) .andExpect(jsonPath("$[1].endDate", Is.is(LocalDate.of(2023, 3, 31).toString()))) .andExpect(jsonPath("$[2].id", Is.is((int) BACK_LOG_QUARTER_ID))) @@ -65,8 +83,10 @@ void shouldGetAllQuarters() throws Exception { void shouldGetAllTeamsIfNoTeamsExists() throws Exception { BDDMockito.given(quarterBusinessService.getQuarters()).willReturn(Collections.emptyList()); - mvc.perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0))); + mvc + .perform(get("/api/v2/quarters").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(0))); } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/controller/TeamControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/TeamControllerIT.java index 999c8cacf1..3aebd55fad 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/TeamControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/TeamControllerIT.java @@ -1,9 +1,18 @@ package ch.puzzle.okr.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.dto.TeamDto; import ch.puzzle.okr.mapper.TeamMapper; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.service.authorization.TeamAuthorizationService; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; @@ -22,16 +31,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(TeamController.class) @@ -87,10 +86,14 @@ void setUp() { void shouldGetAllTeams() throws Exception { BDDMockito.given(teamAuthorizationService.getAllTeams()).willReturn(teamList); - mvc.perform(get("/api/v2/teams?quarterId=1").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(2))) - .andExpect(jsonPath("$[0].id", Is.is(5))).andExpect(jsonPath("$[0].name", Is.is(PUZZLE))) - .andExpect(jsonPath("$[1].id", Is.is(7))).andExpect(jsonPath("$[1].name", Is.is("OKR"))); + mvc + .perform(get("/api/v2/teams?quarterId=1").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(2))) + .andExpect(jsonPath("$[0].id", Is.is(5))) + .andExpect(jsonPath("$[0].name", Is.is(PUZZLE))) + .andExpect(jsonPath("$[1].id", Is.is(7))) + .andExpect(jsonPath("$[1].name", Is.is("OKR"))); } @Test @@ -105,27 +108,37 @@ void shouldGetAllTeamsWhenNoQuarterParamIsPassed() throws Exception { void shouldGetAllTeamsIfTeamModelIsNull() throws Exception { BDDMockito.given(teamAuthorizationService.getAllTeams()).willReturn(Collections.emptyList()); - mvc.perform(get("/api/v2/teams?quarterId=1").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0))); + mvc + .perform(get("/api/v2/teams?quarterId=1").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(0))); } @Test void shouldReturnCreatedTeam() throws Exception { BDDMockito.given(teamAuthorizationService.createEntity(any())).willReturn(teamOKR); - mvc.perform(post(BASE_URL).contentType(MediaType.APPLICATION_JSON).content(CREATE_NEW_TEAM) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(post(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .content(CREATE_NEW_TEAM) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isCreated()) .andExpect(MockMvcResultMatchers.content().string(RESPONSE_NEW_TEAM)); } @Test void shouldReturnResponseStatusExceptionWhenCreatingObjectiveWithNullValues() throws Exception { - BDDMockito.given(teamAuthorizationService.createEntity(any())).willThrow( - new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing attribute name when creating team")); - - mvc.perform(post(BASE_URL).contentType(MediaType.APPLICATION_JSON).content(CREATE_NEW_TEAM_WITH_NULL_VALUES) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + BDDMockito + .given(teamAuthorizationService.createEntity(any())) + .willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Missing attribute name when creating team")); + + mvc + .perform(post(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .content(CREATE_NEW_TEAM_WITH_NULL_VALUES) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isBadRequest()); } @@ -137,8 +150,12 @@ void shouldReturnUpdatedTeam() throws Exception { BDDMockito.given(teamMapper.toDto(any())).willReturn(teamDto); BDDMockito.given(teamAuthorizationService.updateEntity(any(), anyLong())).willReturn(team); - mvc.perform(put(URL_TEAM_1).contentType(MediaType.APPLICATION_JSON).content(UPDATE_TEAM) - .with(SecurityMockMvcRequestPostProcessors.csrf())).andExpect(MockMvcResultMatchers.status().isOk()) + mvc + .perform(put(URL_TEAM_1) + .contentType(MediaType.APPLICATION_JSON) + .content(UPDATE_TEAM) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath("$.id", Is.is(teamDto.id().intValue()))) .andExpect(jsonPath("$.version", Is.is(teamDto.version()))) .andExpect(jsonPath("$.name", Is.is(teamDto.name()))); @@ -146,55 +163,76 @@ void shouldReturnUpdatedTeam() throws Exception { @Test void shouldReturnNotFound() throws Exception { - BDDMockito.given(teamAuthorizationService.updateEntity(any(), anyLong())) + BDDMockito + .given(teamAuthorizationService.updateEntity(any(), anyLong())) .willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Failed team -> Attribut is invalid")); - mvc.perform(put(URL_TEAM_1).contentType(MediaType.APPLICATION_JSON).content(UPDATE_TEAM) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_TEAM_1) + .contentType(MediaType.APPLICATION_JSON) + .content(UPDATE_TEAM) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void shouldReturnBadRequest() throws Exception { - BDDMockito.given(teamAuthorizationService.updateEntity(any(), anyLong())) + BDDMockito + .given(teamAuthorizationService.updateEntity(any(), anyLong())) .willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed team -> Attribut is invalid")); - mvc.perform(put(URL_TEAM_1).contentType(MediaType.APPLICATION_JSON).content(UPDATE_TEAM) - .with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_TEAM_1) + .contentType(MediaType.APPLICATION_JSON) + .content(UPDATE_TEAM) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isBadRequest()); } @Test void shouldDeleteTeam() throws Exception { - mvc.perform(delete(URL_TEAM_1).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(URL_TEAM_1).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void throwExceptionWhenOTeamWithIdCantBeFoundWhileDeleting() throws Exception { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Team not found")).when(teamAuthorizationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "Team not found")) + .when(teamAuthorizationService) .deleteEntity(anyLong()); - mvc.perform(delete(URL_TEAM_1).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete(URL_TEAM_1).with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } @Test void addUsersToTeam_shouldReturnOk() throws Exception { - mvc.perform(put(URL_TEAM_1 + "/addusers").contentType(MediaType.APPLICATION_JSON).content(ADD_USERS) - .with(SecurityMockMvcRequestPostProcessors.csrf())).andExpect(MockMvcResultMatchers.status().isOk()); + mvc + .perform(put(URL_TEAM_1 + "/addusers") + .contentType(MediaType.APPLICATION_JSON) + .content(ADD_USERS) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void removeUserFromTeam_shouldReturnOk() throws Exception { - mvc.perform(put(URL_TEAM_1 + SUB_URL_USER_5 + "/removeuser").contentType(MediaType.APPLICATION_JSON) - .content(ADD_USERS).with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(put(URL_TEAM_1 + SUB_URL_USER_5 + "/removeuser") + .contentType(MediaType.APPLICATION_JSON) + .content(ADD_USERS) + .with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test void updateOrAddTeamMembership_shouldReturnOk() throws Exception { - mvc.perform(put(URL_TEAM_1 + SUB_URL_USER_5 + "/updateaddteammembership/true") - .contentType(MediaType.APPLICATION_JSON).content(ADD_USERS) - .with(SecurityMockMvcRequestPostProcessors.csrf())).andExpect(MockMvcResultMatchers.status().isOk()); + mvc + .perform(put(URL_TEAM_1 + SUB_URL_USER_5 + "/updateaddteammembership/true") + .contentType(MediaType.APPLICATION_JSON) + .content(ADD_USERS) + .with(SecurityMockMvcRequestPostProcessors.csrf())) + .andExpect(MockMvcResultMatchers.status().isOk()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/controller/UserControllerIT.java b/backend/src/test/java/ch/puzzle/okr/controller/UserControllerIT.java index 04cf20eb1c..87219c0775 100644 --- a/backend/src/test/java/ch/puzzle/okr/controller/UserControllerIT.java +++ b/backend/src/test/java/ch/puzzle/okr/controller/UserControllerIT.java @@ -1,11 +1,21 @@ package ch.puzzle.okr.controller; +import static ch.puzzle.okr.controller.ActionControllerIT.SUCCESSFUL_UPDATE_BODY; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.mapper.UserMapper; import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.service.authorization.AuthorizationService; import ch.puzzle.okr.service.authorization.UserAuthorizationService; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.hamcrest.Matchers; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; @@ -25,17 +35,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.server.ResponseStatusException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static ch.puzzle.okr.controller.ActionControllerIT.SUCCESSFUL_UPDATE_BODY; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @WithMockUser(value = "spring") @ExtendWith(MockitoExtension.class) @WebMvcTest(UserController.class) @@ -46,10 +45,20 @@ class UserControllerIT { private static final String FIRSTNAME_2 = "Bob"; private static final String LASTNAME_2 = "Baumeister"; private static final String EMAIL_2 = "baumeister@puzzle.ch"; - static User userAlice = User.Builder.builder().withId(2L).withFirstname(FIRSTNAME_1).withLastname(LASTNAME_1) - .withEmail(EMAIL_1).build(); - static User userBob = User.Builder.builder().withId(9L).withFirstname(FIRSTNAME_2).withLastname(LASTNAME_2) - .withEmail(EMAIL_2).build(); + static User userAlice = User.Builder + .builder() + .withId(2L) + .withFirstname(FIRSTNAME_1) + .withLastname(LASTNAME_1) + .withEmail(EMAIL_1) + .build(); + static User userBob = User.Builder + .builder() + .withId(9L) + .withFirstname(FIRSTNAME_2) + .withLastname(LASTNAME_2) + .withEmail(EMAIL_2) + .build(); static List userList = Arrays.asList(userAlice, userBob); static UserDto userAliceDto = new UserDto(2L, 3, FIRSTNAME_1, LASTNAME_1, EMAIL_1, new ArrayList<>(), false); static UserDto userBobDto = new UserDto(9L, 4, FIRSTNAME_2, LASTNAME_2, EMAIL_2, new ArrayList<>(), false); @@ -72,11 +81,15 @@ void setUp() { void shouldGetAllUsers() throws Exception { BDDMockito.given(userAuthorizationService.getAllUsers()).willReturn(userList); - mvc.perform(get("/api/v1/users").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(2))) - .andExpect(jsonPath("$[0].id", Is.is(2))).andExpect(jsonPath("$[0].firstname", Is.is(FIRSTNAME_1))) + mvc + .perform(get("/api/v1/users").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(2))) + .andExpect(jsonPath("$[0].id", Is.is(2))) + .andExpect(jsonPath("$[0].firstname", Is.is(FIRSTNAME_1))) .andExpect(jsonPath("$[0].lastname", Is.is(LASTNAME_1))) - .andExpect(jsonPath("$[0].email", Is.is(EMAIL_1))).andExpect(jsonPath("$[1].id", Is.is(9))) + .andExpect(jsonPath("$[0].email", Is.is(EMAIL_1))) + .andExpect(jsonPath("$[1].id", Is.is(9))) .andExpect(jsonPath("$[1].firstname", Is.is(FIRSTNAME_2))) .andExpect(jsonPath("$[1].lastname", Is.is(LASTNAME_2))) .andExpect(jsonPath("$[1].email", Is.is(EMAIL_2))); @@ -86,17 +99,21 @@ void shouldGetAllUsers() throws Exception { void shouldGetAllUsersIfNoUserExists() throws Exception { BDDMockito.given(userAuthorizationService.getAllUsers()).willReturn(Collections.emptyList()); - mvc.perform(get("/api/v1/users").contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(0))); + mvc + .perform(get("/api/v1/users").contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", Matchers.hasSize(0))); } @Test void shouldReturnCurrentUser() throws Exception { - BDDMockito.given(authorizationService.updateOrAddAuthorizationUser()) + BDDMockito + .given(authorizationService.updateOrAddAuthorizationUser()) .willReturn(new AuthorizationUser(userAlice)); BDDMockito.given(userMapper.toDto(userAlice)).willReturn(userAliceDto); - mvc.perform(get("/api/v1/users/current").contentType(MediaType.APPLICATION_JSON)) + mvc + .perform(get("/api/v1/users/current").contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(jsonPath("$", Matchers.aMapWithSize(7))) // .andExpect(jsonPath("$.id", Is.is(2))) // @@ -113,7 +130,8 @@ void shouldReturnUserById() throws Exception { BDDMockito.given(userAuthorizationService.getById(2)).willReturn(userAlice); BDDMockito.given(userMapper.toDto(userAlice)).willReturn(userAliceDto); - mvc.perform(get("/api/v1/users/2").contentType(MediaType.APPLICATION_JSON)) // + mvc + .perform(get("/api/v1/users/2").contentType(MediaType.APPLICATION_JSON)) // .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(jsonPath("$", Matchers.aMapWithSize(7))) // .andExpect(jsonPath("$.id", Is.is(2))) // @@ -130,11 +148,12 @@ void shouldSetOkrChampion() throws Exception { BDDMockito.given(userAuthorizationService.setIsOkrChampion(2, true)).willReturn(userAlice); BDDMockito.given(userMapper.toDto(userAlice)).willReturn(userAliceDto); - mvc.perform(put("/api/v1/users/2/isokrchampion/true") // - .content(SUCCESSFUL_UPDATE_BODY) // - .contentType(MediaType.APPLICATION_JSON) // - .with(SecurityMockMvcRequestPostProcessors.csrf()) // - ) // + mvc + .perform(put("/api/v1/users/2/isokrchampion/true") // + .content(SUCCESSFUL_UPDATE_BODY) // + .contentType(MediaType.APPLICATION_JSON) // + .with(SecurityMockMvcRequestPostProcessors.csrf()) // + ) // .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(jsonPath("$", Matchers.aMapWithSize(7))) // .andExpect(jsonPath("$.id", Is.is(2))) // @@ -151,11 +170,12 @@ void shouldCreateUsers() throws Exception { BDDMockito.given(userAuthorizationService.createUsers(any())).willReturn(List.of(userAlice)); BDDMockito.given(userMapper.toDtos(List.of(userAlice))).willReturn(List.of(userAliceDto)); - mvc.perform(post("/api/v1/users/createall") // - .content(SUCCESSFUL_UPDATE_BODY) // - .contentType(MediaType.APPLICATION_JSON) // - .with(SecurityMockMvcRequestPostProcessors.csrf()) // - ) // + mvc + .perform(post("/api/v1/users/createall") // + .content(SUCCESSFUL_UPDATE_BODY) // + .contentType(MediaType.APPLICATION_JSON) // + .with(SecurityMockMvcRequestPostProcessors.csrf()) // + ) // .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(jsonPath("$", Matchers.hasSize(1))) // .andExpect(jsonPath("$[0].id", Is.is(2))) // @@ -169,17 +189,20 @@ void shouldCreateUsers() throws Exception { @Test void shouldDeleteUser() throws Exception { - mvc.perform(delete("/api/v1/users/10").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v1/users/10").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isOk()); } @DisplayName("should throw exception when user with id cant be found while deleting") @Test void throwExceptionWhenUserWithIdCantBeFoundWhileDeleting() throws Exception { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")).when(userAuthorizationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")) + .when(userAuthorizationService) .deleteEntityById(1000); - mvc.perform(delete("/api/v1/users/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) + mvc + .perform(delete("/api/v1/users/1000").with(SecurityMockMvcRequestPostProcessors.csrf())) .andExpect(MockMvcResultMatchers.status().isNotFound()); } diff --git a/backend/src/test/java/ch/puzzle/okr/deserializer/CheckInDeserializerTest.java b/backend/src/test/java/ch/puzzle/okr/deserializer/CheckInDeserializerTest.java index ab9f43c687..2dd743dc58 100644 --- a/backend/src/test/java/ch/puzzle/okr/deserializer/CheckInDeserializerTest.java +++ b/backend/src/test/java/ch/puzzle/okr/deserializer/CheckInDeserializerTest.java @@ -1,12 +1,21 @@ package ch.puzzle.okr.deserializer; +import static ch.puzzle.okr.test.CheckInTestHelpers.*; +import static ch.puzzle.okr.test.CheckInTestHelpers.CHECK_IN_METRIC_JSON; +import static ch.puzzle.okr.test.KeyResultTestHelpers.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; + import ch.puzzle.okr.Constants; import ch.puzzle.okr.models.keyresult.KeyResult; -import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.business.KeyResultBusinessService; import ch.puzzle.okr.test.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; +import java.util.stream.Stream; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -15,17 +24,6 @@ import org.mockito.*; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.CheckInTestHelpers.*; -import static ch.puzzle.okr.test.CheckInTestHelpers.CHECK_IN_METRIC_JSON; -import static ch.puzzle.okr.test.KeyResultTestHelpers.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.times; - @ExtendWith(MockitoExtension.class) class CheckInDeserializerTest { @Mock @@ -55,8 +53,9 @@ void deserializeShouldReturnCheckInMetricDtoForMetricJson() throws Exception { } private static Stream checkInTypes() { - return Stream.of(Arguments.of(metricKeyResult, CHECK_IN_METRIC_JSON, "metric"), - Arguments.of(ordinalKeyResult, CHECK_IN_ORDINAL_JSON, "ordinal")); + return Stream + .of(Arguments.of(metricKeyResult, CHECK_IN_METRIC_JSON, "metric"), + Arguments.of(ordinalKeyResult, CHECK_IN_ORDINAL_JSON, "ordinal")); } @DisplayName("deserialize() should call helper with correct params") diff --git a/backend/src/test/java/ch/puzzle/okr/deserializer/DeserializerHelperTest.java b/backend/src/test/java/ch/puzzle/okr/deserializer/DeserializerHelperTest.java index 7d701d6948..293c8167d1 100644 --- a/backend/src/test/java/ch/puzzle/okr/deserializer/DeserializerHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/deserializer/DeserializerHelperTest.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.deserializer; +import static ch.puzzle.okr.Constants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.checkin.*; import ch.puzzle.okr.dto.keyresult.*; import ch.puzzle.okr.models.Unit; @@ -8,6 +13,7 @@ import ch.puzzle.okr.test.KeyResultTestHelpers; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.*; @@ -15,13 +21,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.Map; - -import static ch.puzzle.okr.Constants.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class DeserializerHelperTest { diff --git a/backend/src/test/java/ch/puzzle/okr/deserializer/KeyResultDeserializerTest.java b/backend/src/test/java/ch/puzzle/okr/deserializer/KeyResultDeserializerTest.java index c1a275e8fa..9d719a5dfd 100644 --- a/backend/src/test/java/ch/puzzle/okr/deserializer/KeyResultDeserializerTest.java +++ b/backend/src/test/java/ch/puzzle/okr/deserializer/KeyResultDeserializerTest.java @@ -1,10 +1,17 @@ package ch.puzzle.okr.deserializer; +import static ch.puzzle.okr.test.KeyResultTestHelpers.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; + import ch.puzzle.okr.Constants; import ch.puzzle.okr.test.KeyResultTestHelpers; import ch.puzzle.okr.test.TestHelper; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,16 +21,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.*; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.http.HttpStatus; -import org.springframework.web.server.ResponseStatusException; - -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.KeyResultTestHelpers.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) class KeyResultDeserializerTest { @@ -61,8 +58,8 @@ void deserializeShouldReturnKeyResultMetricDtoForMetricJson() throws Exception { } private static Stream keyResultTypes() { - return Stream.of(Arguments.of(KEY_RESULT_METRIC_JSON, "metric"), - Arguments.of(KEY_RESULT_ORDINAL_JSON, "ordinal")); + return Stream + .of(Arguments.of(KEY_RESULT_METRIC_JSON, "metric"), Arguments.of(KEY_RESULT_ORDINAL_JSON, "ordinal")); } @DisplayName("deserialize() should call helper with correct params") diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/ActionMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/ActionMapperTest.java index 9dc733ff5e..6dbde44b55 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/ActionMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/ActionMapperTest.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.mapper; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.ActionDto; import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.keyresult.KeyResult; @@ -7,6 +10,7 @@ import ch.puzzle.okr.service.business.KeyResultBusinessService; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; import ch.puzzle.okr.service.validation.KeyResultValidationService; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,11 +18,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class ActionMapperTest { @@ -48,7 +47,8 @@ void setup() { @Test void toDtoShouldMapActionToDto() { // arrange - Action action = Action.Builder.builder() // + Action action = Action.Builder + .builder() // .withId(ID) // .withVersion(VERSION) // .withAction(ACTION) // @@ -107,12 +107,12 @@ void toActionsWithKeyResultParameterShouldMapListOfDtosToListOfActions() { // arrange KeyResult keyResultParameter = KeyResultMetric.Builder.builder().withId(20L).build(); ActionDto actionDtoWithKeyResultIdIsNull = new ActionDto(ID, // - VERSION, // - ACTION, // - PRIORITY, // - IS_CHECKED, // - null, // keyResultId - IS_WRITEABLE // + VERSION, // + ACTION, // + PRIORITY, // + IS_CHECKED, // + null, // keyResultId + IS_WRITEABLE // ); // act @@ -123,7 +123,8 @@ void toActionsWithKeyResultParameterShouldMapListOfDtosToListOfActions() { assertNotNull(actionList); // the value of the KeyResultId in the ActionDto is null - // the value of the KeyResultId in Action is the value of keyResultParameter ( == 20) + // the value of the KeyResultId in Action is the value of keyResultParameter ( + // == 20) assertListOfActionsAndKeyResultParameter(actionDtoList, actionList, keyResultParameter.getId()); } @@ -133,7 +134,7 @@ private void assertListOfActionsWithKeyResultId(List expectedDtoList, } private void assertListOfActionsAndKeyResultParameter(List expectedDtoList, List actualList, - Long keyResultId) { + Long keyResultId) { assertListsAndFirstAction(expectedDtoList, actualList); assertEquals(keyResultId, actualList.get(0).getKeyResult().getId()); } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/AlignmentSelectionMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/AlignmentSelectionMapperTest.java index 84c1db2ff8..2c70cc5a64 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/AlignmentSelectionMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/AlignmentSelectionMapperTest.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.mapper; +import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import ch.puzzle.okr.dto.alignment.AlignmentObjectiveDto; import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.models.alignment.AlignmentSelectionId; -import org.junit.jupiter.api.Test; - import java.util.List; - -import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; class AlignmentSelectionMapperTest { private final AlignmentSelectionMapper alignmentSelectionMapper = new AlignmentSelectionMapper(); @@ -24,9 +23,14 @@ void toDtoShouldReturnEmptyListWhenNoObjectiveFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveFound() { - List alignmentSelections = List.of(AlignmentSelection.Builder.builder() - .withAlignmentSelectionId(AlignmentSelectionId.Builder.builder().withObjectiveId(1L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").build()); + List alignmentSelections = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder.builder().withObjectiveId(1L).build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .build()); List alignmentObjectiveDtos = alignmentSelectionMapper.toDto(alignmentSelections); assertEquals(1, alignmentObjectiveDtos.size()); @@ -35,11 +39,19 @@ void toDtoShouldReturnOneElementWhenObjectiveFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultFound() { - List alignmentSelections = List.of(AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(1L).withKeyResultId(3L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1") - .withKeyResultTitle("Key Result 3").build()); + List alignmentSelections = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(1L) + .withKeyResultId(3L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 3") + .build()); List alignmentObjectiveDtos = alignmentSelectionMapper.toDto(alignmentSelections); assertEquals(1, alignmentObjectiveDtos.size()); @@ -48,17 +60,31 @@ void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveWithTwoKeyResultsFound() { - List alignmentSelections = List.of( - AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(1L).withKeyResultId(3L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1") - .withKeyResultTitle("Key Result 3").build(), - AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(1L).withKeyResultId(5L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1") - .withKeyResultTitle("Key Result 5").build()); + List alignmentSelections = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(1L) + .withKeyResultId(3L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 3") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(1L) + .withKeyResultId(5L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 5") + .build()); List alignmentObjectiveDtos = alignmentSelectionMapper.toDto(alignmentSelections); assertEquals(1, alignmentObjectiveDtos.size()); @@ -67,22 +93,43 @@ void toDtoShouldReturnOneElementWhenObjectiveWithTwoKeyResultsFound() { @Test void toDtoShouldReturnOneElementWhenTwoObjectivesWithKeyResultsFound() { - List alignmentSelections = List.of( - AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(1L).withKeyResultId(3L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1") - .withKeyResultTitle("Key Result 3").build(), - AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(5L).withKeyResultId(6L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 5") - .withKeyResultTitle("Key Result 6").build(), - AlignmentSelection.Builder.builder() - .withAlignmentSelectionId( - AlignmentSelectionId.Builder.builder().withObjectiveId(1L).withKeyResultId(9L).build()) - .withTeamId(2L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1") - .withKeyResultTitle("Key Result 9").build()); + List alignmentSelections = List + .of(AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(1L) + .withKeyResultId(3L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 3") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(5L) + .withKeyResultId(6L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 5") + .withKeyResultTitle("Key Result 6") + .build(), + AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.Builder + .builder() + .withObjectiveId(1L) + .withKeyResultId(9L) + .build()) + .withTeamId(2L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 9") + .build()); List alignmentObjectiveDtos = alignmentSelectionMapper.toDto(alignmentSelections); assertEquals(2, alignmentObjectiveDtos.size()); diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/CompletedMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/CompletedMapperTest.java index cf764ebc6f..cb223a37d0 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/CompletedMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/CompletedMapperTest.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.mapper; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import ch.puzzle.okr.dto.CompletedDto; import ch.puzzle.okr.models.Completed; import ch.puzzle.okr.models.Objective; @@ -17,9 +20,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - @ExtendWith(MockitoExtension.class) public class CompletedMapperTest { private static final long COMPLETED_ID = 0L; @@ -49,10 +49,12 @@ void setUp() { @Test void toDtoShouldMapCompletedToDto() { // arrange - var completed = Completed.Builder.builder() // + var completed = Completed.Builder + .builder() // .withId(COMPLETED_ID) // .withComment(COMPLETED_COMMENT) // - .withObjective(Objective.Builder.builder() // + .withObjective(Objective.Builder + .builder() // .withId(OBJECTIVE_ID)// .withTeam(Team.Builder.builder().withId(NOT_USED_LONG).build()) // .withQuarter(Quarter.Builder.builder().withId(NOT_USED_LONG).build()) // @@ -77,8 +79,12 @@ private void assertCompletedDto(Completed expected, CompletedDto actual) { @Test void toCompletedShouldMapDtoToCompleted() { // arrange - var completedDto = CompletedDtoBuilder.builder().withId(COMPLETED_ID).withComment(COMPLETED_COMMENT) - .withObjectiveDto(ObjectiveDtoBuilder.builder().withId(OBJECTIVE_ID).build()).build(); + var completedDto = CompletedDtoBuilder + .builder() + .withId(COMPLETED_ID) + .withComment(COMPLETED_COMMENT) + .withObjectiveDto(ObjectiveDtoBuilder.builder().withId(OBJECTIVE_ID).build()) + .build(); // act var completed = completedMapper.toCompleted(completedDto); diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/ObjectiveMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/ObjectiveMapperTest.java index 35ce1d1cc7..bd610940f3 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/ObjectiveMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/ObjectiveMapperTest.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.mapper; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.ObjectiveDto; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.Quarter; @@ -7,6 +10,8 @@ import ch.puzzle.okr.models.Team; import ch.puzzle.okr.service.business.QuarterBusinessService; import ch.puzzle.okr.service.business.TeamBusinessService; +import java.time.LocalDateTime; +import java.time.Month; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,12 +21,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.time.LocalDateTime; -import java.time.Month; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class ObjectiveMapperTest { @@ -39,7 +38,8 @@ public class ObjectiveMapperTest { private static final LocalDateTime MODIFIED_DATE_TIME = LocalDateTime.of(2024, Month.MAY, 21, 8, 0, 0); private final Team team = Team.Builder.builder().withId(TEAM_ID).build(); - private final Quarter quarter = Quarter.Builder.builder() // + private final Quarter quarter = Quarter.Builder + .builder() // .withId(QUARTER_ID) // .withLabel(QUARTER_LABEL) // .build(); @@ -61,7 +61,8 @@ void setup() { @Test void toDtoShouldMapObjectiveToDto() { // arrange - Objective objective = Objective.Builder.builder() // + Objective objective = Objective.Builder + .builder() // .withId(ID) // .withVersion(VERSION) // .withTitle(TITLE) // diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/OverviewMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/OverviewMapperTest.java index 49236bb00e..b04dedc890 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/OverviewMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/OverviewMapperTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.mapper; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; +import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.dto.overview.OverviewDto; import ch.puzzle.okr.dto.overview.OverviewKeyResultDto; @@ -9,20 +16,12 @@ import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.models.overview.OverviewId; import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; -import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @ExtendWith(MockitoExtension.class) class OverviewMapperTest { @@ -39,8 +38,12 @@ void toDtoShouldReturnEmptyListWhenNoTeamFound() { @Test void toDtoShouldReturnEmptyListWhenTeamFound() { - List overviews = List.of(Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withTeamId(2L).build()).withTeamName(TEAM_PUZZLE).build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder.builder().withTeamId(2L).build()) + .withTeamName(TEAM_PUZZLE) + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -49,9 +52,13 @@ void toDtoShouldReturnEmptyListWhenTeamFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveFound() { - List overviews = List.of(Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L).build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -61,11 +68,20 @@ void toDtoShouldReturnOneElementWhenObjectiveFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultFound() { - List overviews = List.of(Overview.Builder.builder() - .withOverviewId( - OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L).withKeyResultId(3L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType(KEY_RESULT_TYPE_METRIC).build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -75,11 +91,23 @@ void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultAndCheckInsFound() { - List overviews = List.of(Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L).withKeyResultId(3L) - .withCheckInId(4L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withCheckInValue(27.5).withConfidence(5).build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .withCheckInId(4L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withCheckInValue(27.5) + .withConfidence(5) + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -89,17 +117,35 @@ void toDtoShouldReturnOneElementWhenObjectiveWithKeyResultAndCheckInsFound() { @Test void toDtoShouldReturnOneElementWhenObjectiveWithTwoKeyResultAndCheckInFound() { - List overviews = List.of( - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L) - .withKeyResultId(3L).withCheckInId(4L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType(KEY_RESULT_TYPE_ORDINAL).withCheckInZone("COMMIT").build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L) - .withKeyResultId(5L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 5") - .withKeyResultType(KEY_RESULT_TYPE_METRIC).build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .withCheckInId(4L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType(KEY_RESULT_TYPE_ORDINAL) + .withCheckInZone("COMMIT") + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(5L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 5") + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -109,19 +155,43 @@ void toDtoShouldReturnOneElementWhenObjectiveWithTwoKeyResultAndCheckInFound() { @Test void toDtoShouldReturnOneElementWhenTwoObjectivesWithKeyResultAndCheckInFound() { - List overviews = List.of( - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L) - .withKeyResultId(3L).withCheckInId(4L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType(KEY_RESULT_TYPE_METRIC).withBaseline(20.0).withStretchGoal(37.0) - .withUnit("TCHF").withCheckInValue(27.5).build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(5L).withTeamId(2L) - .withKeyResultId(6L).withCheckInId(7L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 5").withKeyResultTitle("Key Result 6") - .withKeyResultType(KEY_RESULT_TYPE_ORDINAL).withCommitZone("commit").withTargetZone("target") - .withStretchZone("stretch").withCheckInZone("checkIn").build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .withCheckInId(4L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .withBaseline(20.0) + .withStretchGoal(37.0) + .withUnit("TCHF") + .withCheckInValue(27.5) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(5L) + .withTeamId(2L) + .withKeyResultId(6L) + .withCheckInId(7L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 5") + .withKeyResultTitle("Key Result 6") + .withKeyResultType(KEY_RESULT_TYPE_ORDINAL) + .withCommitZone("commit") + .withTargetZone("target") + .withStretchZone("stretch") + .withCheckInZone("checkIn") + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(1, overviewDtos.size()); @@ -147,22 +217,48 @@ void toDtoShouldReturnOneElementWhenTwoObjectivesWithKeyResultAndCheckInFound() @Test void toDtoShouldReturnOneElementWhenTwoTeamsWithObjectivesAndKeyResultsFound() { - List overviews = List.of( - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L) - .withKeyResultId(3L).withCheckInId(4L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType(KEY_RESULT_TYPE_ORDINAL).withCheckInZone("TARGET").build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(5L).withTeamId(4L) - .withKeyResultId(6L).build()) - .withTeamName("/BBT").withObjectiveTitle("Objective 5").withKeyResultTitle("Key Result 6") - .withKeyResultType(KEY_RESULT_TYPE_METRIC).build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(5L).withTeamId(4L) - .withKeyResultId(8L).build()) - .withTeamName("/BBT").withObjectiveTitle("Objective 5").withKeyResultTitle("Key Result 8") - .withKeyResultType(KEY_RESULT_TYPE_ORDINAL).build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .withCheckInId(4L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType(KEY_RESULT_TYPE_ORDINAL) + .withCheckInZone("TARGET") + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(5L) + .withTeamId(4L) + .withKeyResultId(6L) + .build()) + .withTeamName("/BBT") + .withObjectiveTitle("Objective 5") + .withKeyResultTitle("Key Result 6") + .withKeyResultType(KEY_RESULT_TYPE_METRIC) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(5L) + .withTeamId(4L) + .withKeyResultId(8L) + .build()) + .withTeamName("/BBT") + .withObjectiveTitle("Objective 5") + .withKeyResultTitle("Key Result 8") + .withKeyResultType(KEY_RESULT_TYPE_ORDINAL) + .build()); List overviewDtos = overviewMapper.toDto(overviews); assertEquals(2, overviewDtos.size()); @@ -174,14 +270,25 @@ void toDtoShouldReturnOneElementWhenTwoTeamsWithObjectivesAndKeyResultsFound() { @Test void toDtoShouldThrowExceptionWhenKeyResultTypeNotSupported() { - List overviews = List.of(Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(2L).withKeyResultId(3L) - .withCheckInId(4L).build()) - .withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 1").withKeyResultTitle("Key Result 1") - .withKeyResultType("unknown").withCheckInZone("TARGET").build()); + List overviews = List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(1L) + .withTeamId(2L) + .withKeyResultId(3L) + .withCheckInId(4L) + .build()) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 1") + .withKeyResultTitle("Key Result 1") + .withKeyResultType("unknown") + .withCheckInZone("TARGET") + .build()); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> overviewMapper.toDto(overviews)); + () -> overviewMapper.toDto(overviews)); assertEquals(BAD_REQUEST, exception.getStatusCode()); diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/TeamMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/TeamMapperTest.java index a885626375..7ff1416141 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/TeamMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/TeamMapperTest.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.mapper; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.dto.TeamDto; import ch.puzzle.okr.models.Team; import org.junit.jupiter.api.DisplayName; @@ -8,8 +10,6 @@ import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.*; - @ExtendWith(MockitoExtension.class) public class TeamMapperTest { @@ -25,7 +25,8 @@ public class TeamMapperTest { @Test void toDtoShouldMapTeamToDto() { // arrange - Team team = Team.Builder.builder() // + Team team = Team.Builder + .builder() // .withId(ID) // .withVersion(VERSION) // .withName(NAME) // diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/UserMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/UserMapperTest.java index 3677e06a18..0c5b30384c 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/UserMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/UserMapperTest.java @@ -1,10 +1,13 @@ package ch.puzzle.okr.mapper; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.dto.NewUserDto; import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.UserTeam; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -12,10 +15,6 @@ import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - @ExtendWith(MockitoExtension.class) public class UserMapperTest { @@ -32,16 +31,19 @@ public class UserMapperTest { @InjectMocks private TeamMapper teamMapper; - private final User user = User.Builder.builder() // + private final User user = User.Builder + .builder() // .withId(ID) // .withVersion(VERSION) // .withFirstname(FIRSTNAME) // .withLastname(LASTNAME) // .withEmail(EMAIL) // - .withUserTeamList(List.of(UserTeam.Builder.builder() // - .withId(USER_TEAM_ID) // - .withTeam(Team.Builder.builder().build()) // - .build())) // + .withUserTeamList(List + .of(UserTeam.Builder + .builder() // + .withId(USER_TEAM_ID) // + .withTeam(Team.Builder.builder().build()) // + .build())) // .withOkrChampion(IS_OKR_CHAMPION) // .build(); @@ -56,7 +58,8 @@ void setup() { @Test void toDtoWithoutTeamListThrowsException() { // arrange - User user = User.Builder.builder() // + User user = User.Builder + .builder() // .withId(ID) // .withVersion(VERSION) // .withFirstname(FIRSTNAME) // diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMapperTest.java index 514d838491..81ed42beb1 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMapperTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.mapper.checkin; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.checkin.CheckInDto; import ch.puzzle.okr.dto.checkin.CheckInMetricDto; import ch.puzzle.okr.dto.checkin.CheckInOrdinalDto; @@ -21,10 +25,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class CheckInMapperTest { @@ -110,8 +110,8 @@ void toDtoShouldThrowExceptionIfCheckInIsNotMetricOrOrdinal() { // act + assert ResponseStatusException responseStatusException = assertThrows( // - ResponseStatusException.class, // - () -> checkInMapper.toDto(checkIn)); + ResponseStatusException.class, // + () -> checkInMapper.toDto(checkIn)); assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); } @@ -124,8 +124,8 @@ void toCheckInShouldThrowExceptionIfCheckInIsNotMetricOrOrdinal() { // act + assert ResponseStatusException responseStatusException = assertThrows( // - ResponseStatusException.class, // - () -> checkInMapper.toCheckIn(checkInDto)); + ResponseStatusException.class, // + () -> checkInMapper.toCheckIn(checkInDto)); assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapperTest.java index 138391aa35..9ec42fb3fd 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInMetricMapperTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.mapper.checkin; +import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInMetric; +import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInMetricDto; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataDtoHelper.checkInMetricDto; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataHelper.checkInMetric; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.checkin.CheckInMetricDto; import ch.puzzle.okr.mapper.checkin.helper.TestDataHelper; import ch.puzzle.okr.models.checkin.CheckIn; @@ -15,13 +22,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInMetric; -import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInMetricDto; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataDtoHelper.checkInMetricDto; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataHelper.checkInMetric; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class CheckInMetricMapperTest { diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapperTest.java index 76a7900bcf..9fdde46e16 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/CheckInOrdinalMapperTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.mapper.checkin; +import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInOrdinal; +import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInOrdinalDto; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataDtoHelper.checkInOrdinalDto; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataHelper.checkInOrdinal; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.checkin.CheckInOrdinalDto; import ch.puzzle.okr.mapper.checkin.helper.TestDataHelper; import ch.puzzle.okr.models.checkin.CheckIn; @@ -15,13 +22,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInOrdinal; -import static ch.puzzle.okr.mapper.checkin.helper.AssertHelper.assertCheckInOrdinalDto; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataDtoHelper.checkInOrdinalDto; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataHelper.checkInOrdinal; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class CheckInOrdinalMapperTest { diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/AssertHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/AssertHelper.java index 022d72105f..c1fa95407a 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/AssertHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/AssertHelper.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.mapper.checkin.helper; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + import ch.puzzle.okr.dto.checkin.CheckInMetricDto; import ch.puzzle.okr.dto.checkin.CheckInOrdinalDto; import ch.puzzle.okr.models.checkin.CheckInMetric; import ch.puzzle.okr.models.checkin.CheckInOrdinal; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - public class AssertHelper { public static void assertCheckInMetricDto(CheckInMetric expected, CheckInMetricDto actual) { diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataConstants.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataConstants.java index a060a43c11..ad74625cea 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataConstants.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataConstants.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.mapper.checkin.helper; import ch.puzzle.okr.models.checkin.Zone; - import java.time.LocalDateTime; import java.time.Month; diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataDtoHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataDtoHelper.java index f7c7f2ff14..9246a3a10b 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataDtoHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataDtoHelper.java @@ -1,10 +1,10 @@ package ch.puzzle.okr.mapper.checkin.helper; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataConstants.*; + import ch.puzzle.okr.dto.checkin.CheckInMetricDto; import ch.puzzle.okr.dto.checkin.CheckInOrdinalDto; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataConstants.*; - public class TestDataDtoHelper { public static CheckInMetricDto checkInMetricDto() { @@ -16,26 +16,26 @@ public static CheckInOrdinalDto checkInOrdinalDto() { } private static final CheckInMetricDto checkInMetricDto = new CheckInMetricDto(CHECK_IN_ID, // - CHECK_IN_VERSION, // - CHECK_IN_CHANGE_INFO, // - CHECK_IN_INITIATIVES, // - CHECK_IN_CONFIDENCE, // - KEY_RESULT_ID, // - CHECK_IN_CREATE_DATE_TIME, // - CHECK_IN_MODIFIED_DATE_TIME, // - CHECK_IN_METRIC_VALUE, // - CHECK_IN_IS_WRITEABLE // + CHECK_IN_VERSION, // + CHECK_IN_CHANGE_INFO, // + CHECK_IN_INITIATIVES, // + CHECK_IN_CONFIDENCE, // + KEY_RESULT_ID, // + CHECK_IN_CREATE_DATE_TIME, // + CHECK_IN_MODIFIED_DATE_TIME, // + CHECK_IN_METRIC_VALUE, // + CHECK_IN_IS_WRITEABLE // ); private static final CheckInOrdinalDto checkInOrdinalDto = new CheckInOrdinalDto(CHECK_IN_ID, // - CHECK_IN_VERSION, // - CHECK_IN_CHANGE_INFO, // - CHECK_IN_INITIATIVES, // - CHECK_IN_CONFIDENCE, // - KEY_RESULT_ID, // - CHECK_IN_CREATE_DATE_TIME, // - CHECK_IN_MODIFIED_DATE_TIME, // - CHECK_IN_ORDINAL_ZONE, // - CHECK_IN_IS_WRITEABLE // + CHECK_IN_VERSION, // + CHECK_IN_CHANGE_INFO, // + CHECK_IN_INITIATIVES, // + CHECK_IN_CONFIDENCE, // + KEY_RESULT_ID, // + CHECK_IN_CREATE_DATE_TIME, // + CHECK_IN_MODIFIED_DATE_TIME, // + CHECK_IN_ORDINAL_ZONE, // + CHECK_IN_IS_WRITEABLE // ); } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataHelper.java index dc2d43b9c8..f7d493c91a 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/checkin/helper/TestDataHelper.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.mapper.checkin.helper; +import static ch.puzzle.okr.mapper.checkin.helper.TestDataConstants.*; + import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.models.checkin.CheckInMetric; import ch.puzzle.okr.models.checkin.CheckInOrdinal; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; -import static ch.puzzle.okr.mapper.checkin.helper.TestDataConstants.*; - public class TestDataHelper { public static KeyResult keyResult() { @@ -24,11 +24,13 @@ public static CheckInOrdinal checkInOrdinal() { return (CheckInOrdinal) TestDataHelper.checkInOrdinal; } - private static final KeyResult keyResult = KeyResultMetric.Builder.builder() // + private static final KeyResult keyResult = KeyResultMetric.Builder + .builder() // .withId(KEY_RESULT_ID) // .build(); - private static final CheckIn checkInMetric = CheckInMetric.Builder.builder() // + private static final CheckIn checkInMetric = CheckInMetric.Builder + .builder() // .withId(CHECK_IN_ID) // .withVersion(CHECK_IN_VERSION) // .withChangeInfo(CHECK_IN_CHANGE_INFO) // @@ -40,7 +42,8 @@ public static CheckInOrdinal checkInOrdinal() { .withValue(CHECK_IN_METRIC_VALUE) // .build(); - private static final CheckIn checkInOrdinal = CheckInOrdinal.Builder.builder() // + private static final CheckIn checkInOrdinal = CheckInOrdinal.Builder + .builder() // .withId(CHECK_IN_ID) // .withVersion(CHECK_IN_VERSION) // .withChangeInfo(CHECK_IN_CHANGE_INFO) // @@ -49,5 +52,6 @@ public static CheckInOrdinal checkInOrdinal() { .withKeyResult(keyResult) // .withCreatedOn(CHECK_IN_CREATE_DATE_TIME) // .withModifiedOn(CHECK_IN_MODIFIED_DATE_TIME) // - .withZone(CHECK_IN_ORDINAL_ZONE).build(); + .withZone(CHECK_IN_ORDINAL_ZONE) + .build(); } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapperTest.java index 8ba2235adc..4d1177b072 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMapperTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.mapper.keyresult; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.keyResultMetricDto; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.keyResultOrdinalDto; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.keyResultMetric; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.keyResultOrdinal; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.dto.keyresult.KeyResultMetricDto; import ch.puzzle.okr.dto.keyresult.KeyResultOrdinalDto; @@ -11,6 +18,7 @@ import ch.puzzle.okr.service.business.CheckInBusinessService; import ch.puzzle.okr.service.business.ObjectiveBusinessService; import ch.puzzle.okr.service.business.UserBusinessService; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -21,15 +29,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.keyResultMetricDto; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.keyResultOrdinalDto; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.keyResultMetric; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.keyResultOrdinal; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - @ExtendWith(MockitoExtension.class) public class KeyResultMapperTest { @@ -46,16 +45,16 @@ public class KeyResultMapperTest { @BeforeEach void setup() { KeyResultMetricMapper keyResultMetricMapper = new KeyResultMetricMapper( // - userBusinessService, // - objectiveBusinessService, // - checkInBusinessService, // - actionMapper); + userBusinessService, // + objectiveBusinessService, // + checkInBusinessService, // + actionMapper); KeyResultOrdinalMapper keyResultOrdinalMapper = new KeyResultOrdinalMapper( // - userBusinessService, // - objectiveBusinessService, // - checkInBusinessService, // - actionMapper); + userBusinessService, // + objectiveBusinessService, // + checkInBusinessService, // + actionMapper); keyResultMapper = new KeyResultMapper(keyResultOrdinalMapper, keyResultMetricMapper); } @@ -124,8 +123,8 @@ void toDtoShouldThrowExceptionIfKeyResultIsNotMetricOrOrdinal() { // act + assert ResponseStatusException responseStatusException = assertThrows( // - ResponseStatusException.class, // - () -> keyResultMapper.toDto(keyResult, actions)); + ResponseStatusException.class, // + () -> keyResultMapper.toDto(keyResult, actions)); assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); } @@ -137,8 +136,8 @@ void toKeyResultShouldThrowExceptionIfKeyResultDtoIsNotMetricOrOrdinal() { // act + assert ResponseStatusException responseStatusException = assertThrows( // - ResponseStatusException.class, // - () -> keyResultMapper.toKeyResult(keyResultDto)); + ResponseStatusException.class, // + () -> keyResultMapper.toKeyResult(keyResultDto)); assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); } } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapperTest.java index e6efdb524e..7c00f6aaa7 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultMetricMapperTest.java @@ -1,5 +1,11 @@ package ch.puzzle.okr.mapper.keyresult; +import static ch.puzzle.okr.mapper.keyresult.helper.AssertHelper.*; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.dto.keyresult.KeyResultMetricDto; import ch.puzzle.okr.mapper.ActionMapper; @@ -15,6 +21,7 @@ import ch.puzzle.okr.service.business.UserBusinessService; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; import ch.puzzle.okr.service.validation.KeyResultValidationService; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -23,14 +30,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.mapper.keyresult.helper.AssertHelper.*; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.*; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class KeyResultMetricMapperTest { @@ -54,10 +53,10 @@ public class KeyResultMetricMapperTest { void setup() { actionMapper = new ActionMapper(keyResultBusinessService); keyResultMetricMapper = new KeyResultMetricMapper( // - userBusinessService, // - objectiveBusinessService, // - checkInBusinessService, // - actionMapper); + userBusinessService, // + objectiveBusinessService, // + checkInBusinessService, // + actionMapper); } @DisplayName("toDto() should map a KeyResultMetric to a Dto") diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapperTest.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapperTest.java index dbc631e1d5..8fd59853db 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/KeyResultOrdinalMapperTest.java @@ -1,5 +1,11 @@ package ch.puzzle.okr.mapper.keyresult; +import static ch.puzzle.okr.mapper.keyresult.helper.AssertHelper.*; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.keyresult.KeyResultDto; import ch.puzzle.okr.dto.keyresult.KeyResultOrdinalDto; import ch.puzzle.okr.mapper.ActionMapper; @@ -15,6 +21,7 @@ import ch.puzzle.okr.service.business.UserBusinessService; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; import ch.puzzle.okr.service.validation.KeyResultValidationService; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -23,14 +30,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.mapper.keyresult.helper.AssertHelper.*; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataHelper.*; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) public class KeyResultOrdinalMapperTest { @@ -55,10 +54,10 @@ public class KeyResultOrdinalMapperTest { void setup() { actionMapper = new ActionMapper(keyResultBusinessService); keyResultOrdinalMapper = new KeyResultOrdinalMapper( // - userBusinessService, // - objectiveBusinessService, // - checkInBusinessService, // - actionMapper); + userBusinessService, // + objectiveBusinessService, // + checkInBusinessService, // + actionMapper); } @DisplayName("toDto() should map a KeyResultOrdinal with CheckIn to a Dto") diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/AssertHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/AssertHelper.java index fde8f34372..597c9f92e1 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/AssertHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/AssertHelper.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.mapper.keyresult.helper; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.lastCheckInMetricDto; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.dto.ActionDto; import ch.puzzle.okr.dto.keyresult.*; import ch.puzzle.okr.models.Action; @@ -8,18 +13,12 @@ import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; - import java.util.List; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataDtoHelper.lastCheckInMetricDto; -import static org.junit.jupiter.api.Assertions.*; - public class AssertHelper { public static void assertKeyResultMetricDtoWithCheckIn(KeyResultMetric expected, KeyResultMetricDto actual, - List actions) { + List actions) { assertKeyResultMetricDto(expected, actual, actions); // checkIn is only available on KeyResultMetricDto (and not on KeyResultMetric). // So check actual against the checkInMetricDto from TestDataDtoHelper @@ -28,13 +27,13 @@ public static void assertKeyResultMetricDtoWithCheckIn(KeyResultMetric expected, } public static void assertKeyResultMetricDtoWithoutCheckIn(KeyResultMetric expected, KeyResultMetricDto actual, - List actions) { + List actions) { assertKeyResultMetricDto(expected, actual, actions); assertNull(actual.lastCheckIn()); } private static void assertKeyResultMetricDto(KeyResultMetric expected, KeyResultMetricDto actual, - List actions) { + List actions) { assertEquals(KEY_RESULT_TYPE_METRIC, actual.keyResultType()); assertEquals(expected.getKeyResultType(), actual.keyResultType()); @@ -71,22 +70,23 @@ public static void assertKeyResultMetric(KeyResultMetricDto expected, KeyResultM } public static void assertKeyResultOrdinalDtoWithCheckIn(KeyResultOrdinal expected, KeyResultOrdinalDto actual, - List actions) { + List actions) { assertKeyResultOrdinalDto(expected, actual, actions); assertNotNull(actual.lastCheckIn()); assertCheckInOrdinalDto(TestDataDtoHelper.lastCheckInOrdinalDto(), actual.lastCheckIn()); } public static void assertKeyResultOrdinalDtoWithoutCheckIn(KeyResultOrdinal expected, KeyResultOrdinalDto actual, - List actions) { + List actions) { assertKeyResultOrdinalDto(expected, actual, actions); - // checkIn is only available on KeyResultOrdinalDto (and not on KeyResultOrdinal). + // checkIn is only available on KeyResultOrdinalDto (and not on + // KeyResultOrdinal). // So check actual against the KeyResultOrdinalDto from TestDataDtoHelper assertNull(actual.lastCheckIn()); } private static void assertKeyResultOrdinalDto(KeyResultOrdinal expected, KeyResultOrdinalDto actual, - List actions) { + List actions) { assertEquals(KEY_RESULT_TYPE_ORDINAL, actual.keyResultType()); assertEquals(expected.getKeyResultType(), actual.keyResultType()); @@ -170,7 +170,7 @@ private static void assertOwner(KeyResultUserDto expected, User actual) { } private static void assertCheckInMetricDto(KeyResultLastCheckInMetricDto expected, - KeyResultLastCheckInMetricDto actual) { + KeyResultLastCheckInMetricDto actual) { assertEquals(expected.id(), actual.id()); assertEquals(expected.version(), actual.version()); assertEquals(expected.value(), actual.value()); @@ -181,7 +181,7 @@ private static void assertCheckInMetricDto(KeyResultLastCheckInMetricDto expecte } private static void assertCheckInOrdinalDto(KeyResultLastCheckInOrdinalDto expected, - KeyResultLastCheckInOrdinalDto actual) { + KeyResultLastCheckInOrdinalDto actual) { assertEquals(expected.id(), actual.id()); assertEquals(expected.version(), actual.version()); assertEquals(expected.zone(), actual.zone()); diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataConstants.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataConstants.java index eff5381a5a..8e51b53ff3 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataConstants.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataConstants.java @@ -3,7 +3,6 @@ import ch.puzzle.okr.models.State; import ch.puzzle.okr.models.Unit; import ch.puzzle.okr.models.checkin.Zone; - import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataDtoHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataDtoHelper.java index ed836d442b..91344c5026 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataDtoHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataDtoHelper.java @@ -1,11 +1,11 @@ package ch.puzzle.okr.mapper.keyresult.helper; -import ch.puzzle.okr.dto.keyresult.*; - import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; import static ch.puzzle.okr.mapper.keyresult.helper.TestDataConstants.*; +import ch.puzzle.okr.dto.keyresult.*; + public class TestDataDtoHelper { public static KeyResultMetricDto keyResultMetricDto() { return keyResultMetricDto; @@ -24,78 +24,85 @@ public static KeyResultLastCheckInOrdinalDto lastCheckInOrdinalDto() { } private static final KeyResultUserDto ownerDto = new KeyResultUserDto( // - USER_ID, // - USER_FIRSTNAME, // - USER_LASTNAME // + USER_ID, // + USER_FIRSTNAME, // + USER_LASTNAME // ); private static final KeyResultQuarterDto quarterDto = new KeyResultQuarterDto( // - QUARTER_ID, // - QUARTER_LABEL, // - QUARTER_START_DATE, // - QUARTER_END_DATE // + QUARTER_ID, // + QUARTER_LABEL, // + QUARTER_START_DATE, // + QUARTER_END_DATE // ); private static final KeyResultObjectiveDto objectiveDto = new KeyResultObjectiveDto( // - OBJECTIVE_ID, // - OBJECTIVE_STATE.name(), // - quarterDto // + OBJECTIVE_ID, // + OBJECTIVE_STATE.name(), // + quarterDto // ); private static final KeyResultLastCheckInMetricDto lastCheckInMetricDto = new KeyResultLastCheckInMetricDto( // - CHECK_IN_ID, // - CHECK_IN_VERSION, // - CHECK_IN_METRIC_VALUE, // - CHECK_IN_CONFIDENCE, // - CHECK_IN_CREATED_ON, // - CHECK_IN_CHANGE_INFO, // - CHECK_IN_INITIATIVES // + CHECK_IN_ID, // + CHECK_IN_VERSION, // + CHECK_IN_METRIC_VALUE, // + CHECK_IN_CONFIDENCE, // + CHECK_IN_CREATED_ON, // + CHECK_IN_CHANGE_INFO, // + CHECK_IN_INITIATIVES // ); private static final KeyResultLastCheckInOrdinalDto lastCheckInOrdinalDto = new KeyResultLastCheckInOrdinalDto( // - CHECK_IN_ID, // - CHECK_IN_VERSION, // - CHECK_IN_ORDINAL_ZONE, // - CHECK_IN_CONFIDENCE, // - CHECK_IN_CREATED_ON, // - CHECK_IN_CHANGE_INFO, // - CHECK_IN_INITIATIVES // + CHECK_IN_ID, // + CHECK_IN_VERSION, // + CHECK_IN_ORDINAL_ZONE, // + CHECK_IN_CONFIDENCE, // + CHECK_IN_CREATED_ON, // + CHECK_IN_CHANGE_INFO, // + CHECK_IN_INITIATIVES // ); private static final KeyResultMetricDto keyResultMetricDto = new KeyResultMetricDto( // - KEY_RESULT_ID, // - KEY_RESULT_VERSION, // - KEY_RESULT_TYPE_METRIC, // - KEY_RESULT_TITLE, // - KEY_RESULT_DESCRIPTION, // - KEY_RESULT_BASELINE, // - KEY_RESULT_STRETCH_GOAL, // - KEY_RESULT_UNIT, // - ownerDto, // - objectiveDto, // - lastCheckInMetricDto, // - CHECK_IN_CREATED_ON, // - CHECK_IN_MODIFIED_ON, // - CHECK_IN_IS_WRITABLE, // - null // actionList; ony used for keyResultMetric + action -> dto BUT NOT FOR dto -> keyResultMetric + KEY_RESULT_ID, // + KEY_RESULT_VERSION, // + KEY_RESULT_TYPE_METRIC, // + KEY_RESULT_TITLE, // + KEY_RESULT_DESCRIPTION, // + KEY_RESULT_BASELINE, // + KEY_RESULT_STRETCH_GOAL, // + KEY_RESULT_UNIT, // + ownerDto, // + objectiveDto, // + lastCheckInMetricDto, // + CHECK_IN_CREATED_ON, // + CHECK_IN_MODIFIED_ON, // + CHECK_IN_IS_WRITABLE, // + null // actionList; ony used for + // keyResultMetric + action + // -> dto BUT NOT FOR dto + // -> keyResultMetric ); private static final KeyResultOrdinalDto keyResultOrdinalDto = new KeyResultOrdinalDto( // - KEY_RESULT_ID, // - KEY_RESULT_VERSION, // - KEY_RESULT_TYPE_ORDINAL, // - KEY_RESULT_TITLE, // - KEY_RESULT_DESCRIPTION, // - KEY_RESULT_COMMIT_ZONE, // - KEY_RESULT_TARGET_ZONE, // - KEY_RESULT_STRETCH_ZONE, // - ownerDto, // - objectiveDto, // - lastCheckInOrdinalDto, // - CHECK_IN_CREATED_ON, // - CHECK_IN_MODIFIED_ON, // - CHECK_IN_IS_WRITABLE, // - null // actionList; ony used for keyResultOrdinal + action -> dto BUT NOT FOR dto -> keyResultOrdinal + KEY_RESULT_ID, // + KEY_RESULT_VERSION, // + KEY_RESULT_TYPE_ORDINAL, // + KEY_RESULT_TITLE, // + KEY_RESULT_DESCRIPTION, // + KEY_RESULT_COMMIT_ZONE, // + KEY_RESULT_TARGET_ZONE, // + KEY_RESULT_STRETCH_ZONE, // + ownerDto, // + objectiveDto, // + lastCheckInOrdinalDto, // + CHECK_IN_CREATED_ON, // + CHECK_IN_MODIFIED_ON, // + CHECK_IN_IS_WRITABLE, // + null // actionList; ony used + // for keyResultOrdinal + // + action -> dto BUT + // NOT FOR dto -> + // keyResultOrdinal ); } diff --git a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataHelper.java b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataHelper.java index 365999229f..dd69ee4c5f 100644 --- a/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/mapper/keyresult/helper/TestDataHelper.java @@ -1,5 +1,7 @@ package ch.puzzle.okr.mapper.keyresult.helper; +import static ch.puzzle.okr.mapper.keyresult.helper.TestDataConstants.*; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.Quarter; @@ -11,8 +13,6 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; -import static ch.puzzle.okr.mapper.keyresult.helper.TestDataConstants.*; - public class TestDataHelper { public static KeyResultMetric keyResultMetric() { @@ -51,7 +51,8 @@ public static Objective objective() { return objective; } - private static final CheckIn checkInMetric = CheckInMetric.Builder.builder() // + private static final CheckIn checkInMetric = CheckInMetric.Builder + .builder() // .withId(CHECK_IN_ID) // .withVersion(CHECK_IN_VERSION) // .withValue(CHECK_IN_METRIC_VALUE) // @@ -61,7 +62,8 @@ public static Objective objective() { .withInitiatives(CHECK_IN_INITIATIVES) // .build(); - private static final CheckIn checkInOrdinal = CheckInOrdinal.Builder.builder() // + private static final CheckIn checkInOrdinal = CheckInOrdinal.Builder + .builder() // .withId(CHECK_IN_ID) // .withVersion(CHECK_IN_VERSION) // .withZone(CHECK_IN_ORDINAL_ZONE) // @@ -71,26 +73,30 @@ public static Objective objective() { .withInitiatives(CHECK_IN_INITIATIVES) // .build(); - private static final User owner = User.Builder.builder() // + private static final User owner = User.Builder + .builder() // .withId(USER_ID) // .withFirstname(USER_FIRSTNAME) // .withLastname(USER_LASTNAME) // .build(); - private static final Quarter quarter = Quarter.Builder.builder() // + private static final Quarter quarter = Quarter.Builder + .builder() // .withId(QUARTER_ID) // .withLabel(QUARTER_LABEL) // .withStartDate(QUARTER_START_DATE) // .withEndDate(QUARTER_END_DATE) // .build(); - private static final Objective objective = Objective.Builder.builder() // + private static final Objective objective = Objective.Builder + .builder() // .withId(OBJECTIVE_ID) // .withQuarter(quarter) // .withState(OBJECTIVE_STATE) // .build(); - private static final KeyResult keyResultMetric = KeyResultMetric.Builder.builder() // + private static final KeyResult keyResultMetric = KeyResultMetric.Builder + .builder() // .withId(KEY_RESULT_ID) // .withVersion(KEY_RESULT_VERSION) // .withTitle(KEY_RESULT_TITLE) // @@ -104,19 +110,23 @@ public static Objective objective() { .withModifiedOn(CHECK_IN_MODIFIED_ON) // .build(); - private static final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder.builder() // + private static final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder + .builder() // .withId(KEY_RESULT_ID) // .withVersion(KEY_RESULT_VERSION) // .withTitle(KEY_RESULT_TITLE) // .withDescription(KEY_RESULT_DESCRIPTION) // - .withCommitZone(KEY_RESULT_COMMIT_ZONE).withTargetZone(KEY_RESULT_TARGET_ZONE) - .withStretchZone(KEY_RESULT_STRETCH_ZONE).withOwner(owner) // + .withCommitZone(KEY_RESULT_COMMIT_ZONE) + .withTargetZone(KEY_RESULT_TARGET_ZONE) + .withStretchZone(KEY_RESULT_STRETCH_ZONE) + .withOwner(owner) // .withObjective(objective) // .withCreatedOn(CHECK_IN_CREATED_ON) // .withModifiedOn(CHECK_IN_MODIFIED_ON) // .build(); - private static final Action actionForKeyResultMetric = Action.Builder.builder() // + private static final Action actionForKeyResultMetric = Action.Builder + .builder() // .withId(ACTION_ID) // .withVersion(ACTION_VERSION) // .withAction(ACTION_ACTION) // @@ -125,7 +135,8 @@ public static Objective objective() { .withKeyResult(keyResultMetric) // .build(); - private static final Action actionForKeyResultOrdinal = Action.Builder.builder() // + private static final Action actionForKeyResultOrdinal = Action.Builder + .builder() // .withId(ACTION_ID) // .withVersion(ACTION_VERSION) // .withAction(ACTION_ACTION) // diff --git a/backend/src/test/java/ch/puzzle/okr/models/authorization/AuthorizationUserTest.java b/backend/src/test/java/ch/puzzle/okr/models/authorization/AuthorizationUserTest.java index 2b74f3dc69..b4283d82bc 100644 --- a/backend/src/test/java/ch/puzzle/okr/models/authorization/AuthorizationUserTest.java +++ b/backend/src/test/java/ch/puzzle/okr/models/authorization/AuthorizationUserTest.java @@ -1,22 +1,21 @@ package ch.puzzle.okr.models.authorization; -import ch.puzzle.okr.test.TestHelper; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.UserTeam; -import org.junit.jupiter.api.Test; - +import ch.puzzle.okr.test.TestHelper; import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; class AuthorizationUserTest { - private final List userTeamList = List.of( - UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(1L)).withTeamAdmin(true).build(), - UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(2L)).withTeamAdmin(false).build(), - UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(3L)).withTeamAdmin(true).build(), - UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(4L)).withTeamAdmin(false).build(), - UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(5L)).withTeamAdmin(false).build()); + private final List userTeamList = List + .of(UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(1L)).withTeamAdmin(true).build(), + UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(2L)).withTeamAdmin(false).build(), + UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(3L)).withTeamAdmin(true).build(), + UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(4L)).withTeamAdmin(false).build(), + UserTeam.Builder.builder().withTeam(TestHelper.defaultTeam(5L)).withTeamAdmin(false).build()); private final User user = User.Builder.builder().withUserTeamList(userTeamList).build(); private final AuthorizationUser authorizationUser = new AuthorizationUser(user); diff --git a/backend/src/test/java/ch/puzzle/okr/models/keyresult/KeyResultTest.java b/backend/src/test/java/ch/puzzle/okr/models/keyresult/KeyResultTest.java index 47b2561baf..c6edc5f1f9 100644 --- a/backend/src/test/java/ch/puzzle/okr/models/keyresult/KeyResultTest.java +++ b/backend/src/test/java/ch/puzzle/okr/models/keyresult/KeyResultTest.java @@ -1,13 +1,12 @@ package ch.puzzle.okr.models.keyresult; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - class KeyResultTest { @ParameterizedTest @@ -20,8 +19,9 @@ void resetIdShouldSetIdToNull(KeyResult keyResult) { } private static Stream provideKeyResults() { - return Stream.of(Arguments.of(KeyResultMetric.Builder.builder().withId(1L).build()), - Arguments.of(KeyResultOrdinal.Builder.builder().withId(1L).build())); + return Stream + .of(Arguments.of(KeyResultMetric.Builder.builder().withId(1L).build()), + Arguments.of(KeyResultOrdinal.Builder.builder().withId(1L).build())); } } \ No newline at end of file diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/CurrentTenantIdentifierResolverImplTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/CurrentTenantIdentifierResolverImplTest.java index 87d82c4c21..d51702037a 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/CurrentTenantIdentifierResolverImplTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/CurrentTenantIdentifierResolverImplTest.java @@ -1,11 +1,11 @@ package ch.puzzle.okr.multitenancy; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + public class CurrentTenantIdentifierResolverImplTest { @DisplayName("current TenantId is TenantId from TenantContext") diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializerTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializerTest.java index 3ab1cb4eb4..a0dbbf5269 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializerTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/FlywayMultitenantMigrationInitializerTest.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.multitenancy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +import java.util.List; +import java.util.Optional; import org.flywaydb.core.Flyway; import org.flywaydb.core.api.configuration.FluentConfiguration; import org.junit.jupiter.api.DisplayName; @@ -7,20 +12,18 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; - /** - * Test for FlywayMultitenantMigrationInitializer.migrateFlyway(). The FlywayMultitenantMigrationInitializer constructor - * gets a mock implementation of a TenantConfigProviderInterface, which provides some test data. Inside migrateFlyway(), - * there are two calls to Flyway: Flyway.configure() (a static method) and flyway.migrate() (an instance method). - * Flyway.configure() returns a FluentConfiguration. Then several method calls are made on the FluentConfiguration, - * which also return a FluentConfiguration. The last calls is load(), which returns a Flyway Object. We can mock that - * with a manual Spy FluentConfigurationSpy, which records the methods calls and load() returns a Mockito Mock, which - * does nothing. And later, flyway.migrate() is called on the Mockito Mock, which does nothing. + * Test for FlywayMultitenantMigrationInitializer.migrateFlyway(). The + * FlywayMultitenantMigrationInitializer constructor gets a mock implementation + * of a TenantConfigProviderInterface, which provides some test data. Inside + * migrateFlyway(), there are two calls to Flyway: Flyway.configure() (a static + * method) and flyway.migrate() (an instance method). Flyway.configure() returns + * a FluentConfiguration. Then several method calls are made on the + * FluentConfiguration, which also return a FluentConfiguration. The last calls + * is load(), which returns a Flyway Object. We can mock that with a manual Spy + * FluentConfigurationSpy, which records the methods calls and load() returns a + * Mockito Mock, which does nothing. And later, flyway.migrate() is called on + * the Mockito Mock, which does nothing. */ public class FlywayMultitenantMigrationInitializerTest { @@ -54,7 +57,8 @@ public FluentConfiguration schemas(String... schemas) { return this; } - // the result of load() is used by flyway.migrate(), which we don't test. So load() returns a mock which does + // the result of load() is used by flyway.migrate(), which we don't test. So + // load() returns a mock which does // nothing. @Override public Flyway load() { @@ -68,11 +72,19 @@ public String getLog() { private final TenantConfigProviderInterface providerInterfaceMock = new TenantConfigProviderInterface() { - private final TenantConfigProvider.DataSourceConfig dataSourceConfig = new TenantConfigProvider.DataSourceConfig( - NOT_USED, URL, NAME, PASSWORD, SCHEMA); + private final TenantConfigProvider.DataSourceConfig dataSourceConfig = new TenantConfigProvider.DataSourceConfig(NOT_USED, + URL, + NAME, + PASSWORD, + SCHEMA); private final TenantConfigProvider.TenantConfig tenantConfig = new TenantConfigProvider.TenantConfig(NOT_USED, - new String[] { NOT_USED }, NOT_USED, NOT_USED, NOT_USED, dataSourceConfig); + new String[]{ + NOT_USED }, + NOT_USED, + NOT_USED, + NOT_USED, + dataSourceConfig); @Override public List getTenantConfigs() { @@ -98,8 +110,9 @@ void flywayConfigureShouldReturnFluentConfigurationWhichWeCanAssert() { FluentConfigurationSpy fluentConfiguration = new FluentConfigurationSpy(); mockedStatic.when(Flyway::configure).thenReturn(fluentConfiguration); - FlywayMultitenantMigrationInitializer migrationInitializer = new FlywayMultitenantMigrationInitializer( - providerInterfaceMock, new String[] { SCRIPT_LOCATION }); + FlywayMultitenantMigrationInitializer migrationInitializer = new FlywayMultitenantMigrationInitializer(providerInterfaceMock, + new String[]{ + SCRIPT_LOCATION }); // act migrationInitializer.migrateFlyway(); diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/HibernateContextTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/HibernateContextTest.java index 7dbc3a5b16..53e4b1bce5 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/HibernateContextTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/HibernateContextTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.multitenancy; +import static ch.puzzle.okr.multitenancy.HibernateContext.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Properties; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -8,14 +15,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.core.env.ConfigurableEnvironment; -import java.util.Properties; -import java.util.stream.Stream; - -import static ch.puzzle.okr.multitenancy.HibernateContext.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class HibernateContextTest { @BeforeEach @@ -38,7 +37,7 @@ void setHibernateConfigShouldThrowExceptionIfDbConfigIsNull() { @ParameterizedTest @MethodSource("invalidDbConfig") void setHibernateConfigShouldThrowExceptionIfDbConfigHasNullOrEmptyValues(String url, String username, - String password, String tenant) { + String password, String tenant) { // arrange DbConfig dbConfig = new DbConfig(url, username, password, tenant); @@ -49,15 +48,16 @@ void setHibernateConfigShouldThrowExceptionIfDbConfigHasNullOrEmptyValues(String } private static Stream invalidDbConfig() { - return Stream.of( // - Arguments.of(null, "username", "password", "multiTenancy"), // - Arguments.of("", "username", "password", "multiTenancy"), // - Arguments.of("url", null, "password", "multiTenancy"), // - Arguments.of("url", "", "password", "multiTenancy"), // - Arguments.of("url", "username", null, "multiTenancy"), // - Arguments.of("url", "username", "", "multiTenancy"), // - Arguments.of("url", "username", "password", null), // - Arguments.of("url", "username", "password", "")); + return Stream + .of( // + Arguments.of(null, "username", "password", "multiTenancy"), // + Arguments.of("", "username", "password", "multiTenancy"), // + Arguments.of("url", null, "password", "multiTenancy"), // + Arguments.of("url", "", "password", "multiTenancy"), // + Arguments.of("url", "username", null, "multiTenancy"), // + Arguments.of("url", "username", "", "multiTenancy"), // + Arguments.of("url", "username", "password", null), // + Arguments.of("url", "username", "password", "")); } @DisplayName("extractAndSetHibernateConfig() should extract hibernate properties from environment and set it") @@ -108,7 +108,7 @@ void getHibernateConfigShouldReturnHibernateConfigAsPropertiesIfDbConfigIsValid( } private void assertProperties(String url, String username, String password, String multiTenancy, - Properties properties) { + Properties properties) { assertEquals(url, properties.get(HIBERNATE_CONNECTION_URL)); assertEquals(username, properties.get(HIBERNATE_CONNECTION_USERNAME)); diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderInternalsTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderInternalsTest.java index e8bc0dc7b0..d160620805 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderInternalsTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderInternalsTest.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.multitenancy; +import static org.mockito.Mockito.mock; + import ch.puzzle.okr.exception.ConnectionProviderException; +import java.util.Properties; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.Properties; - -import static org.mockito.Mockito.mock; - public class SchemaMultiTenantConnectionProviderInternalsTest { private static final String TENANT_ID = "pitc"; diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderTest.java index e9a97a6d14..cb1b61be46 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/SchemaMultiTenantConnectionProviderTest.java @@ -1,16 +1,15 @@ package ch.puzzle.okr.multitenancy; -import ch.puzzle.okr.test.SpringIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import ch.puzzle.okr.test.SpringIntegrationTest; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; @SpringIntegrationTest public class SchemaMultiTenantConnectionProviderTest { diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/TenantConfigProviderTestIT.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/TenantConfigProviderTestIT.java index 940473d020..261538bf80 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/TenantConfigProviderTestIT.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/TenantConfigProviderTestIT.java @@ -1,6 +1,12 @@ package ch.puzzle.okr.multitenancy; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.test.SpringIntegrationTest; +import java.text.MessageFormat; +import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,13 +16,6 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.core.env.Environment; -import java.text.MessageFormat; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - @SpringIntegrationTest @SpringBootConfiguration public class TenantConfigProviderTestIT { @@ -139,7 +138,7 @@ private void assertTenantConfigProvider(TenantConfigProvider.TenantConfig tenant assertEquals(prefix(tenantId) + DATASOURCE_PASSWORD, tenantConfig.dataSourceConfig().password()); assertEquals(prefix(tenantId) + DATASOURCE_SCHEMA, tenantConfig.dataSourceConfig().schema()); - assertArrayEquals(new String[] { CHAMPION_EMAILS_1, CHAMPION_EMAILS_2 }, tenantConfig.okrChampionEmails()); + assertArrayEquals(new String[]{ CHAMPION_EMAILS_1, CHAMPION_EMAILS_2 }, tenantConfig.okrChampionEmails()); assertEquals(DRIVER_CLASS_NAME, tenantConfig.dataSourceConfig().driverClassName()); } diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTest.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTest.java index 9d5a393af0..85aba67421 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTest.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTest.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.multitenancy.customization; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class TenantClientCustomizationProviderTest { @DisplayName("extractCssNameFromPropertyName() should return css name for valid property name") @@ -16,8 +16,8 @@ public class TenantClientCustomizationProviderTest { void extractCssNameFromPropertyNameShouldReturnCssNameForValidPropertyName(String tenantId) { // arrange String propertyNameWithTenant = "okr.tenants." + tenantId - + ".clientcustomization.customstyles.my-css-property-name"; - TenantClientCustomizationProvider provider = new TenantClientCustomizationProvider(new String[] {}, null); + + ".clientcustomization.customstyles.my-css-property-name"; + TenantClientCustomizationProvider provider = new TenantClientCustomizationProvider(new String[]{}, null); // act String cssName = provider.extractCssNameFromPropertyName(propertyNameWithTenant, tenantId); @@ -31,10 +31,10 @@ void extractCssNameFromPropertyNameShouldReturnCssNameForValidPropertyName(Strin void extractCssNameFromPropertyNameShouldThrowIllegalArgumentExceptionForInvalidPropertyName() { // arrange String propertyNameWithoutTenant = "okr.tenants.clientcustomization.customstyles.my-css-property-name"; - TenantClientCustomizationProvider provider = new TenantClientCustomizationProvider(new String[] {}, null); + TenantClientCustomizationProvider provider = new TenantClientCustomizationProvider(new String[]{}, null); // act + assert assertThrows(IllegalArgumentException.class, - () -> provider.extractCssNameFromPropertyName(propertyNameWithoutTenant, "pitc")); + () -> provider.extractCssNameFromPropertyName(propertyNameWithoutTenant, "pitc")); } } diff --git a/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTestIT.java b/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTestIT.java index f1c5806aea..94e0be8fed 100644 --- a/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTestIT.java +++ b/backend/src/test/java/ch/puzzle/okr/multitenancy/customization/TenantClientCustomizationProviderTestIT.java @@ -1,6 +1,11 @@ package ch.puzzle.okr.multitenancy.customization; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.test.SpringIntegrationTest; +import java.text.MessageFormat; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; @@ -8,12 +13,6 @@ import org.mockito.Mock; import org.springframework.core.env.Environment; -import java.text.MessageFormat; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - @SpringIntegrationTest public class TenantClientCustomizationProviderTestIT { private static final String LOGO = "logo"; @@ -45,8 +44,9 @@ private void setupPropertiesForTenantWithId(String id) { mockProperty("okr.tenants.{0}.clientcustomization.favicon", FAVICON, id); mockProperty("okr.tenants.{0}.clientcustomization.title", TITLE, id); mockProperty("okr.tenants.{0}.clientcustomization.helpSiteUrl", HELP_SITE_URL, id); - mockProperty("okr.tenants.{0}.clientcustomization.customstyles.okr-topbar-background-color", CUSTOM_STYLE_VALUE, - id); + mockProperty("okr.tenants.{0}.clientcustomization.customstyles.okr-topbar-background-color", + CUSTOM_STYLE_VALUE, + id); } private void mockProperty(String propertyName, String propertyValue, String tenantId) { diff --git a/backend/src/test/java/ch/puzzle/okr/security/AuthenticationEventsTest.java b/backend/src/test/java/ch/puzzle/okr/security/AuthenticationEventsTest.java index f73c3ecf83..371c3a3b33 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/AuthenticationEventsTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/AuthenticationEventsTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.security; +import static ch.puzzle.okr.multitenancy.TenantContext.DEFAULT_TENANT_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.multitenancy.TenantContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -8,10 +12,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.jwt.Jwt; -import static ch.puzzle.okr.multitenancy.TenantContext.DEFAULT_TENANT_ID; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; - public class AuthenticationEventsTest { public static final String TENANT_FROM_TOKEN = "pitc"; @@ -54,7 +54,7 @@ private void assertTenantFromTokenIsInTenantContext() { } private void verifyGetTenantFromTokenIsCalledWithTokenFromAuthenticationSuccessEvent(JwtHelper jwtHelper, - Jwt token) { + Jwt token) { verify(jwtHelper).getTenantFromToken(token); } diff --git a/backend/src/test/java/ch/puzzle/okr/security/JwtHelperTest.java b/backend/src/test/java/ch/puzzle/okr/security/JwtHelperTest.java index 35f0367478..750615e0be 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/JwtHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/JwtHelperTest.java @@ -1,23 +1,22 @@ package ch.puzzle.okr.security; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; import ch.puzzle.okr.multitenancy.TenantConfigProvider; import com.nimbusds.jwt.JWTClaimsSet; import jakarta.persistence.EntityNotFoundException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.security.oauth2.jwt.Jwt; - import java.text.ParseException; import java.util.Map; import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.BAD_REQUEST; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.security.oauth2.jwt.Jwt; public class JwtHelperTest { @@ -37,14 +36,21 @@ public class JwtHelperTest { void getUserFromJwtExtractsUserDataFromToken() { // arrange Jwt tokenWithUserDataMock = mock(Jwt.class); - when(tokenWithUserDataMock.getClaims()).thenReturn(Map.of( // - TOKEN_CLAIMS_KEY_FIRSTNAME, HANS, // - TOKEN_CLAIMS_KEY_LASTNAME, MUSTER, // - TOKEN_CLAIMS_KEY_EMAIL, EMAIL // - )); + when(tokenWithUserDataMock.getClaims()) + .thenReturn(Map + .of( // + TOKEN_CLAIMS_KEY_FIRSTNAME, + HANS, // + TOKEN_CLAIMS_KEY_LASTNAME, + MUSTER, // + TOKEN_CLAIMS_KEY_EMAIL, + EMAIL // + )); JwtHelper jwtHelper = new JwtHelper(null, // - TOKEN_CLAIMS_KEY_FIRSTNAME, TOKEN_CLAIMS_KEY_LASTNAME, TOKEN_CLAIMS_KEY_EMAIL); + TOKEN_CLAIMS_KEY_FIRSTNAME, + TOKEN_CLAIMS_KEY_LASTNAME, + TOKEN_CLAIMS_KEY_EMAIL); // act User userFromToken = jwtHelper.getUserFromJwt(tokenWithUserDataMock); @@ -63,7 +69,9 @@ void getUserFromJwtThrowsExceptionIfTokenNotContainsUserData() { Jwt tokenWithNoUserDataMock = mock(Jwt.class); JwtHelper jwtHelper = new JwtHelper(null, // - TOKEN_CLAIMS_KEY_FIRSTNAME, TOKEN_CLAIMS_KEY_LASTNAME, TOKEN_CLAIMS_KEY_EMAIL); + TOKEN_CLAIMS_KEY_FIRSTNAME, + TOKEN_CLAIMS_KEY_LASTNAME, + TOKEN_CLAIMS_KEY_EMAIL); // act + assert OkrResponseStatusException okrResponseStatusException = // @@ -81,11 +89,16 @@ void getTenantFromTokenReturnsTenantIfTenantFoundInTenantConfigProvider() { when(tokenMock.getClaimAsString(TOKEN_CLAIMS_KEY_TENANT)).thenReturn(PITC); TenantConfigProvider tenantConfigProviderMock = mock(TenantConfigProvider.class); - when(tenantConfigProviderMock.getTenantConfigById(PITC)).thenReturn(Optional.of( // - new TenantConfigProvider.TenantConfig(PITC, // - new String[] {}, "jwkSetUri", "issuerUrl", // - "clientId", null) // - )); + when(tenantConfigProviderMock.getTenantConfigById(PITC)) + .thenReturn(Optional + .of( // + new TenantConfigProvider.TenantConfig(PITC, // + new String[]{}, + "jwkSetUri", + "issuerUrl", // + "clientId", + null) // + )); JwtHelper jwtHelper = new JwtHelper(tenantConfigProviderMock, null, null, null); @@ -119,11 +132,16 @@ void getTenantFromJWTClaimsSetReturnsTenantIfTenantFoundInTenantConfigProvider() when(claimsSetMock.getStringClaim(TOKEN_CLAIMS_KEY_TENANT)).thenReturn(PITC); TenantConfigProvider tenantConfigProviderWithDataMock = mock(TenantConfigProvider.class); - when(tenantConfigProviderWithDataMock.getTenantConfigById(PITC)).thenReturn(Optional.of( // - new TenantConfigProvider.TenantConfig(PITC, // - new String[] {}, "jwkSetUri", "issuerUrl", // - "clientId", null) // - )); + when(tenantConfigProviderWithDataMock.getTenantConfigById(PITC)) + .thenReturn(Optional + .of( // + new TenantConfigProvider.TenantConfig(PITC, // + new String[]{}, + "jwkSetUri", + "issuerUrl", // + "clientId", + null) // + )); JwtHelper jwtHelper = new JwtHelper(tenantConfigProviderWithDataMock, null, null, null); diff --git a/backend/src/test/java/ch/puzzle/okr/security/TenantJWSKeySelectorTest.java b/backend/src/test/java/ch/puzzle/okr/security/TenantJWSKeySelectorTest.java index f02c34d5c1..42d99ee4ef 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/TenantJWSKeySelectorTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/TenantJWSKeySelectorTest.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.security; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.multitenancy.TenantConfigProvider; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.KeySourceException; import com.nimbusds.jose.proc.JWSKeySelector; import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jwt.JWTClaimsSet; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import java.security.Key; import java.util.List; import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class TenantJWSKeySelectorTest { private static final String PITC = "pitc"; @@ -40,7 +39,10 @@ void selectKeysThrowsExceptionIfTenantConfigIsNotFound() { // act + assert TenantJWSKeySelector selector = new TenantJWSKeySelector(emptyTenantConfigProviderMock, jwtHelperMock); IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, // - () -> selector.selectKeys(jwsHeaderMock, jwtClaimsSetMock, securityContext)); + () -> selector + .selectKeys(jwsHeaderMock, + jwtClaimsSetMock, + securityContext)); assertEquals(UNKNOWN_TENANT, illegalArgumentException.getLocalizedMessage()); } diff --git a/backend/src/test/java/ch/puzzle/okr/security/TenantJwtIssuerValidatorTest.java b/backend/src/test/java/ch/puzzle/okr/security/TenantJwtIssuerValidatorTest.java index 7c675c4204..e59787ada0 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/TenantJwtIssuerValidatorTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/TenantJwtIssuerValidatorTest.java @@ -1,19 +1,18 @@ package ch.puzzle.okr.security; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.multitenancy.TenantConfigProvider; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtIssuerValidator; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class TenantJwtIssuerValidatorTest { private static final String PITC = "pitc"; @@ -48,13 +47,19 @@ void validateReturnOAuth2TokenValidatorResultIfTenantConfigWithIssuerUrlIsFound( when(jwtHelper.getTenantFromToken(token)).thenReturn(PITC); TenantConfigProvider tenantConfigProviderWithPitcConfig = mock(TenantConfigProvider.class); - when(tenantConfigProviderWithPitcConfig.getTenantConfigById(PITC)).thenReturn(Optional.of( // - new TenantConfigProvider.TenantConfig( // - PITC, new String[] {}, "jwkSetUri", // - ISSUER_URL, "clientId", null))); - - TenantJwtIssuerValidator tenantJwtIssuerValidator = new TenantJwtIssuerValidator( - tenantConfigProviderWithPitcConfig, jwtHelper) { + when(tenantConfigProviderWithPitcConfig.getTenantConfigById(PITC)) + .thenReturn(Optional + .of( // + new TenantConfigProvider.TenantConfig( // + PITC, + new String[]{}, + "jwkSetUri", // + ISSUER_URL, + "clientId", + null))); + + TenantJwtIssuerValidator tenantJwtIssuerValidator = new TenantJwtIssuerValidator(tenantConfigProviderWithPitcConfig, + jwtHelper) { @Override JwtIssuerValidator createValidator(String issuer) { diff --git a/backend/src/test/java/ch/puzzle/okr/security/helper/ClaimHelperTest.java b/backend/src/test/java/ch/puzzle/okr/security/helper/ClaimHelperTest.java index 0a3850bf1f..2774d76675 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/helper/ClaimHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/helper/ClaimHelperTest.java @@ -1,15 +1,5 @@ package ch.puzzle.okr.security.helper; -import com.nimbusds.jwt.JWTClaimsSet; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.text.ParseException; -import java.util.Optional; - import static ch.puzzle.okr.security.JwtHelper.CLAIM_ISS; import static ch.puzzle.okr.security.JwtHelper.CLAIM_TENANT; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -17,6 +7,15 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.nimbusds.jwt.JWTClaimsSet; +import java.text.ParseException; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + public class ClaimHelperTest { private static final String PITC = "pitc"; diff --git a/backend/src/test/java/ch/puzzle/okr/security/helper/TokenHelperTest.java b/backend/src/test/java/ch/puzzle/okr/security/helper/TokenHelperTest.java index 0b9c2215ce..e258ccfb72 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/helper/TokenHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/helper/TokenHelperTest.java @@ -1,14 +1,5 @@ package ch.puzzle.okr.security.helper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.security.oauth2.jwt.Jwt; - -import java.util.Optional; - import static ch.puzzle.okr.security.JwtHelper.CLAIM_ISS; import static ch.puzzle.okr.security.JwtHelper.CLAIM_TENANT; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,6 +7,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.security.oauth2.jwt.Jwt; + public class TokenHelperTest { private static final String PITC = "pitc"; diff --git a/backend/src/test/java/ch/puzzle/okr/security/helper/UrlHelperTest.java b/backend/src/test/java/ch/puzzle/okr/security/helper/UrlHelperTest.java index 76f71a918e..7e772e34f1 100644 --- a/backend/src/test/java/ch/puzzle/okr/security/helper/UrlHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/security/helper/UrlHelperTest.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.security.helper; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; - public class UrlHelperTest { private static final String PITC = "pitc"; diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/ActionAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/ActionAuthorizationServiceTest.java index 7e113dea5d..950fc4e9dd 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/ActionAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/ActionAuthorizationServiceTest.java @@ -1,10 +1,18 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.business.ActionBusinessService; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -15,15 +23,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class ActionAuthorizationServiceTest { @InjectMocks @@ -35,10 +34,22 @@ class ActionAuthorizationServiceTest { private final AuthorizationUser authorizationUser = defaultAuthorizationUser(); private final KeyResult keyResult = KeyResultMetric.Builder.builder().withId(10L).withTitle("KR Title").build(); - private final Action action1 = Action.Builder.builder().withId(1L).withAction("Neue Katze").withIsChecked(false) - .withPriority(0).withKeyResult(keyResult).build(); - private final Action action2 = Action.Builder.builder().withId(2L).withAction("Neues Lama").withIsChecked(true) - .withPriority(1).withKeyResult(keyResult).build(); + private final Action action1 = Action.Builder + .builder() + .withId(1L) + .withAction("Neue Katze") + .withIsChecked(false) + .withPriority(0) + .withKeyResult(keyResult) + .build(); + private final Action action2 = Action.Builder + .builder() + .withId(2L) + .withAction("Neues Lama") + .withIsChecked(true) + .withPriority(1) + .withKeyResult(keyResult) + .build(); private final List actionList = List.of(action1, action2); @ParameterizedTest @@ -71,11 +82,12 @@ void createEntityShouldReturnCreatedActionWhenAuthorized() { void createEntityShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(actionList.get(0).getKeyResult(), authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> actionAuthorizationService.createEntities(actionList)); + () -> actionAuthorizationService.createEntities(actionList)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -93,11 +105,12 @@ void updateEntitiesShouldUpdateActionWhenAuthorized() { void updateEntitiesShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(actionList.get(0).getKeyResult(), authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> actionAuthorizationService.updateEntities(actionList)); + () -> actionAuthorizationService.updateEntities(actionList)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -117,11 +130,12 @@ void deleteEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 8L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleDeleteByActionId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> actionAuthorizationService.deleteActionByActionId(id)); + () -> actionAuthorizationService.deleteActionByActionId(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationServiceIT.java index 4f0e3c77e4..71b0285a5b 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationRegistrationServiceIT.java @@ -1,22 +1,21 @@ package ch.puzzle.okr.service.authorization; -import ch.puzzle.okr.test.TestHelper; +import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; +import static ch.puzzle.okr.test.TestHelper.defaultUser; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.service.persistence.UserPersistenceService; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.Optional; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; -import java.util.Optional; - -import static ch.puzzle.okr.SpringCachingConfig.AUTHORIZATION_USER_CACHE; -import static ch.puzzle.okr.test.TestHelper.defaultUser; -import static org.junit.jupiter.api.Assertions.*; - @SpringIntegrationTest class AuthorizationRegistrationServiceIT { @Autowired @@ -86,7 +85,8 @@ void registerAuthorizationUserShouldAddAuthorizationUserToCache() { @Test void registerAuthorizationUser_shouldSetOkrChampionsToFalse() { // arrange - User user = User.Builder.builder() // + User user = User.Builder + .builder() // .withFirstname("Richard") // .withLastname("Eberhard") // .withEmail("richard.eberhard@puzzle.ch") // email not found in application-integration-test.properties @@ -109,11 +109,14 @@ void registerAuthorizationUser_shouldSetOkrChampionsToFalse() { } /* - * Special test setup.
 - the user wunderland@puzzle.ch is an existing user in the H2 db (created via
-     * V100_0_0__TestData.sql) - the user wunderland@puzzle.ch is also defined in
-     * application-integration-test.properties as user champion - with this combination we can test, that the user in
-     * the db (which has initial isOkrChampion == false) is after calling updateOrAddAuthorizationUser() a user
-     * champion. - the OkrChampion status must manually be reset (in the tearDown method) 
+ * Special test setup.
 - the user wunderland@puzzle.ch is an existing user
+     * in the H2 db (created via V100_0_0__TestData.sql) - the user
+     * wunderland@puzzle.ch is also defined in
+     * application-integration-test.properties as user champion - with this
+     * combination we can test, that the user in the db (which has initial
+     * isOkrChampion == false) is after calling updateOrAddAuthorizationUser() a
+     * user champion. - the OkrChampion status must manually be reset (in the
+     * tearDown method) 
*/ @Test @DisplayName("registerAuthorizationUser for a user with an email defined in the application-integration-test.properties should set OkrChampions to true") @@ -123,9 +126,11 @@ void registerAuthorizationUserShouldSetOkrChampionsToTrue() { // act // load user from db (by email) and set OkrChampion status based on property - // "okr.tenants.pitc.user.champion.emails" from application-integration-test.properties file + // "okr.tenants.pitc.user.champion.emails" from + // application-integration-test.properties file AuthorizationUser processedUser = authorizationRegistrationService - .updateOrAddAuthorizationUser(User.Builder.builder() // + .updateOrAddAuthorizationUser(User.Builder + .builder() // .withFirstname("Alice") // .withLastname("Wunderland") // .withEmail(EMAIL_WUNDERLAND) // user.champion.emails from @@ -140,7 +145,8 @@ void registerAuthorizationUserShouldSetOkrChampionsToTrue() { @Test void registerAuthorizationUser_shouldSetFirstnameAndLastnameFromToken() { // arrange - User user = User.Builder.builder() // + User user = User.Builder + .builder() // .withFirstname("Richard") // .withLastname("Eberhard") // .withEmail("richard.eberhard@puzzle.ch") // @@ -149,7 +155,8 @@ void registerAuthorizationUser_shouldSetFirstnameAndLastnameFromToken() { String firstNameFromToken = "Richu"; String lastNameFromToken = "von Gunten"; - User userFromToken = User.Builder.builder() // + User userFromToken = User.Builder + .builder() // .withFirstname(firstNameFromToken) // .withLastname(lastNameFromToken) // .withEmail("richard.eberhard@puzzle.ch") // diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationServiceTest.java index af6812b245..8aa1fab898 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/AuthorizationServiceTest.java @@ -1,5 +1,16 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.ErrorKey.*; +import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; +import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteForTeam; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -13,6 +24,8 @@ import ch.puzzle.okr.security.JwtHelper; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.test.TestHelper; +import java.util.Collection; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -24,20 +37,6 @@ import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.oauth2.jwt.Jwt; -import java.util.Collection; -import java.util.List; - -import static ch.puzzle.okr.ErrorKey.*; -import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAndReadAll; -import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteForTeam; -import static ch.puzzle.okr.test.TestHelper.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class AuthorizationServiceTest { @InjectMocks @@ -49,12 +48,15 @@ class AuthorizationServiceTest { @Mock JwtHelper jwtHelper; - private final List adminTeams = List.of(Team.Builder.builder().withName("Team 1").withId(1L).build(), - Team.Builder.builder().withName("Team 2").withId(2L).build()); - private final List memberTeams = List.of(Team.Builder.builder().withName("Team 3").withId(3L).build(), - Team.Builder.builder().withName("Team 4").withId(4L).build()); - private final List otherTeams = List.of(Team.Builder.builder().withName("Team 5").withId(5L).build(), - Team.Builder.builder().withName("Team 6").withId(6L).build()); + private final List adminTeams = List + .of(Team.Builder.builder().withName("Team 1").withId(1L).build(), + Team.Builder.builder().withName("Team 2").withId(2L).build()); + private final List memberTeams = List + .of(Team.Builder.builder().withName("Team 3").withId(3L).build(), + Team.Builder.builder().withName("Team 4").withId(4L).build()); + private final List otherTeams = List + .of(Team.Builder.builder().withName("Team 5").withId(5L).build(), + Team.Builder.builder().withName("Team 6").withId(6L).build()); private final User user = defaultUserWithTeams(1L, adminTeams, memberTeams); private final User okrChampion = defaultOkrChampion(1L); @@ -122,14 +124,16 @@ void hasRoleReadByObjectiveIdShouldPassThroughWhenPermitted() { void hasRoleReadByKeyResultIdShouldThrowExceptionWhenObjectiveNotFound() { Long id = 13L; AuthorizationUser authorizationUser = new AuthorizationUser(user); - OkrResponseStatusException expectedException = OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, - "KeyResult"); + OkrResponseStatusException expectedException = OkrResponseStatusException + .of(NOT_AUTHORIZED_TO_READ, "KeyResult"); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(id), eq(authorizationUser), any())) .thenThrow(expectedException); OkrResponseStatusException actualException = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleReadByKeyResultId(id, authorizationUser)); + () -> authorizationService + .hasRoleReadByKeyResultId(id, + authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_READ, "KeyResult")); @@ -142,8 +146,8 @@ void hasRoleReadByKeyResultIdShouldThrowExceptionWhenObjectiveNotFound() { void hasRoleReadByKeyResultIdShouldPassThroughWhenPermitted() { Long id = 13L; AuthorizationUser authorizationUser = new AuthorizationUser(user); - OkrResponseStatusException expectedException = OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, - "KeyResult"); + OkrResponseStatusException expectedException = OkrResponseStatusException + .of(NOT_AUTHORIZED_TO_READ, "KeyResult"); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(id), eq(authorizationUser), any())) .thenReturn(new Objective()); @@ -155,13 +159,15 @@ void hasRoleReadByCheckInIdShouldThrowExceptionWhenObjectiveNotFound() { Long id = 13L; AuthorizationUser authorizationUser = new AuthorizationUser(user); - OkrResponseStatusException expectedException = OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, - "Check-in"); + OkrResponseStatusException expectedException = OkrResponseStatusException + .of(NOT_AUTHORIZED_TO_READ, "Check-in"); when(objectivePersistenceService.findObjectiveByCheckInId(eq(id), eq(authorizationUser), any())) .thenThrow(expectedException); OkrResponseStatusException actualException = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleReadByCheckInId(id, authorizationUser)); + () -> authorizationService + .hasRoleReadByCheckInId(id, + authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_READ, "Check-in")); @@ -174,8 +180,8 @@ void hasRoleReadByCheckInIdShouldThrowExceptionWhenObjectiveNotFound() { void hasRoleReadByCheckInIdShouldPassThroughWhenPermitted() { Long id = 13L; AuthorizationUser authorizationUser = new AuthorizationUser(user); - OkrResponseStatusException expectedException = OkrResponseStatusException.of(NOT_AUTHORIZED_TO_READ, - "Check-in"); + OkrResponseStatusException expectedException = OkrResponseStatusException + .of(NOT_AUTHORIZED_TO_READ, "Check-in"); when(objectivePersistenceService.findObjectiveByCheckInId(eq(id), eq(authorizationUser), any())) .thenReturn(new Objective()); @@ -214,7 +220,9 @@ void hasRoleCreateOrUpdateShouldThrowExceptionWhenNotInTeam() { AuthorizationUser authorizationUser = new AuthorizationUser(user); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleCreateOrUpdate(objective, authorizationUser)); + () -> authorizationService + .hasRoleCreateOrUpdate(objective, + authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_WRITE, "Objective")); @@ -229,8 +237,9 @@ void hasRoleCreateOrUpdateShouldPassThroughWhenAuthorizedForKeyResults() { KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = new AuthorizationUser(okrChampion); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); authorizationService.hasRoleCreateOrUpdate(keyResult, authorizationUser); } @@ -242,8 +251,9 @@ void hasRoleCreateOrUpdateShouldPassThroughWhenAuthorizedAsAdminForKeyResults() KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); authorizationService.hasRoleCreateOrUpdate(keyResult, authorizationUser); } @@ -255,11 +265,14 @@ void hasRoleCreateOrUpdateShouldThrowExceptionWhenNotAuthorizedForKeyResults() { KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleCreateOrUpdate(keyResult, authorizationUser)); + () -> authorizationService + .hasRoleCreateOrUpdate(keyResult, + authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_WRITE, "KeyResult")); @@ -276,8 +289,11 @@ void hasRoleCreateOrUpdateShouldPassThroughWhenAuthorizedAsAdminForTeamCheckIns( CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), + eq(authorizationUser), + any())) + .thenReturn(objective); authorizationService.hasRoleCreateOrUpdate(checkIn, authorizationUser); } @@ -290,8 +306,11 @@ void hasRoleCreateOrUpdateShouldPassThroughWhenAuthorizedAsMemberForTeamCheckIns CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), + eq(authorizationUser), + any())) + .thenReturn(objective); authorizationService.hasRoleCreateOrUpdate(checkIn, authorizationUser); } @@ -304,11 +323,15 @@ void hasRoleCreateOrUpdateShouldThrowExceptionWhenNotInTeamForTeamCheckIns() { CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getObjective().getId()), + eq(authorizationUser), + any())) + .thenReturn(objective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleCreateOrUpdate(checkIn, authorizationUser)); + () -> authorizationService + .hasRoleCreateOrUpdate(checkIn, authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_WRITE, "Check-in")); @@ -359,7 +382,9 @@ void hasRoleCreateOrUpdateByObjectiveIdShouldThrowExceptionWhenNotInTeam() { when(objectivePersistenceService.findObjectiveById(eq(id), eq(authorizationUser), any())).thenReturn(objective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleCreateOrUpdateByObjectiveId(id, authorizationUser)); + () -> authorizationService + .hasRoleCreateOrUpdateByObjectiveId(id, + authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_WRITE, "Objective")); @@ -410,8 +435,9 @@ void hasRoleWriteForTeamShouldReturnTrueWhenAuthorizedToWriteAllKeyResults() { KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = new AuthorizationUser(okrChampion); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertTrue(authorizationService.hasRoleWriteForTeam(keyResult, authorizationUser)); } @@ -423,8 +449,9 @@ void hasRoleWriteForTeamShouldReturnTrueWhenAuthorizedAsAdminForKeyResults() { KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertTrue(authorizationService.hasRoleWriteForTeam(keyResult, authorizationUser)); } @@ -435,8 +462,9 @@ void hasRoleWriteForTeamShouldReturnFalseWhenNotAuthorizedToWriteKeyResults() { KeyResult keyResult = KeyResultMetric.Builder.builder().withObjective(objective).build(); AuthorizationUser authorizationUser = mockAuthorizationUser(user); - when(objectivePersistenceService.findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), - any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveById(eq(keyResult.getObjective().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertFalse(authorizationService.hasRoleWriteForTeam(keyResult, authorizationUser)); } @@ -448,8 +476,9 @@ void hasRoleWriteForTeamShouldReturnTrueWhenAuthorizedToWriteAllCheckIns() { CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = new AuthorizationUser(okrChampion); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertTrue(authorizationService.hasRoleWriteForTeam(checkIn, authorizationUser)); } @@ -462,8 +491,9 @@ void hasRoleWriteForTeamShouldReturnTrueWhenAuthorizedAsAdminForCheckIns() { CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertTrue(authorizationService.hasRoleWriteForTeam(checkIn, authorizationUser)); } @@ -475,8 +505,9 @@ void hasRoleWriteForTeamShouldReturnFalseWhenNotAuthorizedToWriteCheckIns() { CheckIn checkIn = CheckInMetric.Builder.builder().withKeyResult(keyResult).build(); AuthorizationUser authorizationUser = mockAuthorizationUser(user); - when(objectivePersistenceService.findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), - eq(authorizationUser), any())).thenReturn(objective); + when(objectivePersistenceService + .findObjectiveByKeyResultId(eq(checkIn.getKeyResult().getId()), eq(authorizationUser), any())) + .thenReturn(objective); assertFalse(authorizationService.hasRoleWriteForTeam(checkIn, authorizationUser)); } @@ -531,7 +562,9 @@ void hasRoleDeleteByCheckInIdShouldPassThroughWhenAuthorizedAsMemberForTeamCheck @Test void hasRoleDeleteByKeyResultIdShouldPassThroughWhenOkrChampion() { var otherTeamId = otherTeams.get(0).getId(); - Objective objective = Objective.Builder.builder().withTeam(Team.Builder.builder().withId(otherTeamId).build()) + Objective objective = Objective.Builder + .builder() + .withTeam(Team.Builder.builder().withId(otherTeamId).build()) .build(); AuthorizationUser authorizationUser = new AuthorizationUser(okrChampion); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(1L), eq(authorizationUser), any())) @@ -543,7 +576,9 @@ void hasRoleDeleteByKeyResultIdShouldPassThroughWhenOkrChampion() { @Test void hasRoleDeleteByKeyResultIdShouldPassThroughWhenAdmin() { var otherTeamId = adminTeams.get(0).getId(); - Objective objective = Objective.Builder.builder().withTeam(Team.Builder.builder().withId(otherTeamId).build()) + Objective objective = Objective.Builder + .builder() + .withTeam(Team.Builder.builder().withId(otherTeamId).build()) .build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(1L), eq(authorizationUser), any())) @@ -555,7 +590,9 @@ void hasRoleDeleteByKeyResultIdShouldPassThroughWhenAdmin() { @Test void hasRoleDeleteByKeyResultIdShouldPassThroughWhenMember() { var otherTeamId = memberTeams.get(0).getId(); - Objective objective = Objective.Builder.builder().withTeam(Team.Builder.builder().withId(otherTeamId).build()) + Objective objective = Objective.Builder + .builder() + .withTeam(Team.Builder.builder().withId(otherTeamId).build()) .build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(1L), eq(authorizationUser), any())) @@ -567,14 +604,17 @@ void hasRoleDeleteByKeyResultIdShouldPassThroughWhenMember() { @Test void hasRoleDeleteByKeyResultIdShouldThrowExceptionWhenNotInTeam() { var otherTeamId = otherTeams.get(0).getId(); - Objective objective = Objective.Builder.builder().withTeam(Team.Builder.builder().withId(otherTeamId).build()) + Objective objective = Objective.Builder + .builder() + .withTeam(Team.Builder.builder().withId(otherTeamId).build()) .build(); AuthorizationUser authorizationUser = new AuthorizationUser(user); when(objectivePersistenceService.findObjectiveByKeyResultId(eq(1L), eq(authorizationUser), any())) .thenReturn(objective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> authorizationService.hasRoleDeleteByKeyResultId(1L, authorizationUser)); + () -> authorizationService + .hasRoleDeleteByKeyResultId(1L, authorizationUser)); List expectedErrors = List.of(ErrorDto.of(NOT_AUTHORIZED_TO_DELETE, "KeyResult")); diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationServiceTest.java index c2cf02731e..96a0c6a2c1 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/CheckInAuthorizationServiceTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.CheckInTestHelpers.checkInMetric; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.service.business.CheckInBusinessService; @@ -11,13 +18,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import static ch.puzzle.okr.test.CheckInTestHelpers.checkInMetric; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class CheckInAuthorizationServiceTest { @InjectMocks @@ -55,11 +55,12 @@ void getEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleReadByCheckInId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> checkInAuthorizationService.getEntityById(id)); + () -> checkInAuthorizationService.getEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -77,11 +78,12 @@ void createEntityShouldReturnCreatedCheckInWhenAuthorized() { void createEntityShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(checkInMetric, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> checkInAuthorizationService.createEntity(checkInMetric)); + () -> checkInAuthorizationService.createEntity(checkInMetric)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -101,11 +103,13 @@ void updateEntityShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(checkInMetric, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> checkInAuthorizationService.updateEntity(id, checkInMetric)); + () -> checkInAuthorizationService + .updateEntity(id, checkInMetric)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -123,11 +127,12 @@ void deleteEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleDeleteByCheckInId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> checkInAuthorizationService.deleteEntityById(id)); + () -> checkInAuthorizationService.deleteEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationServiceTest.java index 2358188144..e134637ef9 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/CompletedAuthorizationServiceTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.models.Completed; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.authorization.AuthorizationUser; @@ -12,13 +19,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class CompletedAuthorizationServiceTest { @InjectMocks @@ -30,8 +30,11 @@ class CompletedAuthorizationServiceTest { private final AuthorizationUser authorizationUser = defaultAuthorizationUser(); private final Long objectiveId = 12L; - private final Completed newCompleted = Completed.Builder.builder().withId(5L) - .withObjective(Objective.Builder.builder().withId(objectiveId).withTitle("Completed 1").build()).build(); + private final Completed newCompleted = Completed.Builder + .builder() + .withId(5L) + .withObjective(Objective.Builder.builder().withId(objectiveId).withTitle("Completed 1").build()) + .build(); @Test void createCompletedShouldReturnObjectiveWhenAuthorized() { @@ -46,11 +49,13 @@ void createCompletedShouldReturnObjectiveWhenAuthorized() { void createCompletedShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdateByObjectiveId(objectiveId, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> completedAuthorizationService.createCompleted(newCompleted)); + () -> completedAuthorizationService + .createCompleted(newCompleted)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -66,11 +71,13 @@ void deleteCompletedByObjectiveIdShouldPassThroughWhenAuthorized() { void deleteCompletedByObjectiveIdShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleDeleteByObjectiveId(objectiveId, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> completedAuthorizationService.deleteCompletedByObjectiveId(objectiveId)); + () -> completedAuthorizationService + .deleteCompletedByObjectiveId(objectiveId)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationServiceTest.java index 2888e08a8a..fb01a84d47 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/KeyResultAuthorizationServiceTest.java @@ -1,10 +1,21 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.KeyResultTestHelpers.checkIn1; +import static ch.puzzle.okr.test.KeyResultTestHelpers.metricKeyResult; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultWithActionList; import ch.puzzle.okr.service.business.KeyResultBusinessService; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,18 +25,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static ch.puzzle.okr.test.KeyResultTestHelpers.checkIn1; -import static ch.puzzle.okr.test.KeyResultTestHelpers.metricKeyResult; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class KeyResultAuthorizationServiceTest { @InjectMocks @@ -49,11 +48,13 @@ void createEntityShouldReturnKeyResultWhenAuthorized() { void createEntityShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(metricKeyResult, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> keyResultAuthorizationService.createEntity(metricKeyResult)); + () -> keyResultAuthorizationService + .createEntity(metricKeyResult)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -84,11 +85,12 @@ void getEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleReadByKeyResultId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> keyResultAuthorizationService.getEntityById(id)); + () -> keyResultAuthorizationService.getEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -100,8 +102,8 @@ void updateEntitiesShouldReturnUpdatedKeyResultWhenAuthorized() { when(keyResultBusinessService.updateEntities(id, metricKeyResult, List.of())) .thenReturn(new KeyResultWithActionList(metricKeyResult, List.of())); - KeyResultWithActionList KeyResult = keyResultAuthorizationService.updateEntities(id, metricKeyResult, - List.of()); + KeyResultWithActionList KeyResult = keyResultAuthorizationService + .updateEntities(id, metricKeyResult, List.of()); assertEquals(metricKeyResult, KeyResult.keyResult()); } @@ -110,11 +112,13 @@ void updateEntitiesShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(metricKeyResult, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> keyResultAuthorizationService.updateEntities(id, metricKeyResult, List.of())); + () -> keyResultAuthorizationService + .updateEntities(id, metricKeyResult, List.of())); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -122,10 +126,12 @@ void updateEntitiesShouldThrowExceptionWhenNotAuthorized() { @Test void updateEntityShouldThrowException() { ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> keyResultAuthorizationService.updateEntity(1L, metricKeyResult)); + () -> keyResultAuthorizationService + .updateEntity(1L, metricKeyResult)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertEquals("unsupported method in class " + KeyResultAuthorizationService.class.getSimpleName() - + ", use updateEntities() instead", exception.getReason()); + + ", use updateEntities() instead", + exception.getReason()); } @Test @@ -141,11 +147,12 @@ void deleteEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleDeleteByKeyResultId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> keyResultAuthorizationService.deleteEntityById(id)); + () -> keyResultAuthorizationService.deleteEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationServiceTest.java index 05a4c8338a..17abfa6b6e 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/ObjectiveAuthorizationServiceTest.java @@ -1,10 +1,19 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.KeyResultTestHelpers.metricKeyResult; +import static ch.puzzle.okr.test.KeyResultTestHelpers.ordinalKeyResult; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; -import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.business.ObjectiveBusinessService; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,17 +23,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.ArrayList; -import java.util.List; - -import static ch.puzzle.okr.test.KeyResultTestHelpers.metricKeyResult; -import static ch.puzzle.okr.test.KeyResultTestHelpers.ordinalKeyResult; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class ObjectiveAuthorizationServiceTest { @InjectMocks @@ -50,11 +48,13 @@ void createEntityShouldReturnObjectiveWhenAuthorized() { void createEntityShouldThrowExceptionWhenNotAuthorized() { String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(newObjective, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> objectiveAuthorizationService.createEntity(newObjective)); + () -> objectiveAuthorizationService + .createEntity(newObjective)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -85,11 +85,12 @@ void getEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleReadByObjectiveId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> objectiveAuthorizationService.getEntityById(id)); + () -> objectiveAuthorizationService.getEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -109,11 +110,13 @@ void updateEntityShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(newObjective, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> objectiveAuthorizationService.updateEntity(id, newObjective)); + () -> objectiveAuthorizationService + .updateEntity(id, newObjective)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -138,11 +141,12 @@ void deleteEntityByIdShouldThrowExceptionWhenNotAuthorized() { Long id = 13L; String reason = "junit test reason"; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleDeleteByObjectiveId(id, authorizationUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> objectiveAuthorizationService.deleteEntityById(id)); + () -> objectiveAuthorizationService.deleteEntityById(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals(reason, exception.getReason()); } @@ -159,12 +163,16 @@ void duplicateEntityShouldThrowExceptionWhenNotAuthorized() { keyResults.add(metricKeyResult); when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)).when(authorizationService) + doThrow(new ResponseStatusException(HttpStatus.UNAUTHORIZED, reason)) + .when(authorizationService) .hasRoleCreateOrUpdate(objective, authorizationUser); // act ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> objectiveAuthorizationService.duplicateEntity(idExistingObjective, objective, keyResults)); + () -> objectiveAuthorizationService + .duplicateEntity(idExistingObjective, + objective, + keyResults)); // assert assertEquals(UNAUTHORIZED, exception.getStatusCode()); @@ -177,22 +185,28 @@ void duplicateEntityShouldReturnDuplicatedObjectiveWhenAuthorized() { // arrange Long idExistingObjective = 13L; - Objective newObjectiveWithoutKeyResults = Objective.Builder.builder() // - .withTitle("Objective without KeyResults").build(); + Objective newObjectiveWithoutKeyResults = Objective.Builder + .builder() // + .withTitle("Objective without KeyResults") + .build(); - Objective newObjectiveWithKeyResults = Objective.Builder.builder() // - .withId(42L).withTitle("Objective with Id and KeyResults").build(); + Objective newObjectiveWithKeyResults = Objective.Builder + .builder() // + .withId(42L) + .withTitle("Objective with Id and KeyResults") + .build(); List keyResults = new ArrayList<>(); keyResults.add(metricKeyResult); when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(authorizationUser); - when(objectiveBusinessService.duplicateObjective(idExistingObjective, newObjectiveWithoutKeyResults, - authorizationUser, keyResults)).thenReturn(newObjectiveWithKeyResults); + when(objectiveBusinessService + .duplicateObjective(idExistingObjective, newObjectiveWithoutKeyResults, authorizationUser, keyResults)) + .thenReturn(newObjectiveWithKeyResults); // act - Objective objective = objectiveAuthorizationService.duplicateEntity(idExistingObjective, - newObjectiveWithoutKeyResults, keyResults); + Objective objective = objectiveAuthorizationService + .duplicateEntity(idExistingObjective, newObjectiveWithoutKeyResults, keyResults); // assert assertEquals(newObjectiveWithKeyResults, objective); diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationServiceTest.java index e2ced700f8..a329da5c29 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/OverviewAuthorizationServiceTest.java @@ -1,9 +1,18 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.models.overview.OverviewId; import ch.puzzle.okr.service.business.OverviewBusinessService; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -13,16 +22,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class OverviewAuthorizationServiceTest { @Mock @@ -35,12 +34,17 @@ class OverviewAuthorizationServiceTest { private final long adminTeamId = 5L; private final long memberTeamId = 6L; - private final AuthorizationUser authorizationUser = new AuthorizationUser( - defaultUserWithTeams(1L, List.of(defaultTeam(adminTeamId)), List.of(defaultTeam(memberTeamId)))); + private final AuthorizationUser authorizationUser = new AuthorizationUser(defaultUserWithTeams(1L, + List + .of(defaultTeam(adminTeamId)), + List + .of(defaultTeam(memberTeamId)))); private final AuthorizationUser okrChampionUser = new AuthorizationUser(defaultOkrChampion(2L)); - private final Overview overview = Overview.Builder.builder() + private final Overview overview = Overview.Builder + .builder() .withOverviewId(OverviewId.Builder.builder().withObjectiveId(1L).withTeamId(adminTeamId).build()) - .withObjectiveTitle("Objective 1").build(); + .withObjectiveTitle("Objective 1") + .build(); @DisplayName("getFilteredOverview() should do nothing when OverviewId is null") @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/TeamAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/TeamAuthorizationServiceTest.java index 6fb9ec4f34..1a5fa86566 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/TeamAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/TeamAuthorizationServiceTest.java @@ -1,9 +1,17 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.service.business.TeamBusinessService; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -13,15 +21,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ExtendWith(MockitoExtension.class) class TeamAuthorizationServiceTest { @@ -34,12 +33,15 @@ class TeamAuthorizationServiceTest { private final AuthorizationUser okrChampionUser = new AuthorizationUser(defaultOkrChampion(1L)); private final Team teamUnderTest = Team.Builder.builder().withId(5L).withName("Team").build(); - private final AuthorizationUser adminUser = new AuthorizationUser( - defaultUserWithTeams(1L, List.of(teamUnderTest), List.of())); - private final AuthorizationUser memberUser = new AuthorizationUser( - defaultUserWithTeams(1L, List.of(), List.of(teamUnderTest))); - private final AuthorizationUser userWithNoTeams = new AuthorizationUser( - defaultUserWithTeams(1L, List.of(), List.of())); + private final AuthorizationUser adminUser = new AuthorizationUser(defaultUserWithTeams(1L, + List.of(teamUnderTest), + List.of())); + private final AuthorizationUser memberUser = new AuthorizationUser(defaultUserWithTeams(1L, + List.of(), + List.of(teamUnderTest))); + private final AuthorizationUser userWithNoTeams = new AuthorizationUser(defaultUserWithTeams(1L, + List.of(), + List.of())); @Test void createEntityShouldReturnTeam() { @@ -75,7 +77,8 @@ void updateEntityShouldThrowExceptionWhenAuthorizedAsMemberUser() { Long id = 13L; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(memberUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> teamAuthorizationService.updateEntity(teamUnderTest, id)); + () -> teamAuthorizationService + .updateEntity(teamUnderTest, id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals("NOT_AUTHORIZED_TO_WRITE", exception.getReason()); } @@ -85,7 +88,8 @@ void updateEntityShouldThrowExceptionWhenAuthorizedAsUserWithNoTeams() { Long id = 13L; when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(userWithNoTeams); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> teamAuthorizationService.updateEntity(teamUnderTest, id)); + () -> teamAuthorizationService + .updateEntity(teamUnderTest, id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals("NOT_AUTHORIZED_TO_WRITE", exception.getReason()); } @@ -118,7 +122,7 @@ void deleteEntityByIdShouldThrowExceptionWhenAuthorizedAsUserWithNoTeams() { when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(userWithNoTeams); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> teamAuthorizationService.deleteEntity(id)); + () -> teamAuthorizationService.deleteEntity(id)); assertEquals(UNAUTHORIZED, exception.getStatusCode()); assertEquals("NOT_AUTHORIZED_TO_DELETE", exception.getReason()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java index e1c8a23229..03e38ecd6c 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java @@ -1,9 +1,14 @@ package ch.puzzle.okr.service.authorization; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.service.business.UserBusinessService; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -11,12 +16,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) public class UserAuthorizationServiceTest { @Mock @@ -80,7 +79,7 @@ void setOkrChampion_shouldThrowErrorIfLoggedInUserIsNotOkrChampion() { when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(new AuthorizationUser(loggedInUser)); assertThrows(OkrResponseStatusException.class, - () -> userAuthorizationService.setIsOkrChampion(user.getId(), true)); + () -> userAuthorizationService.setIsOkrChampion(user.getId(), true)); } @Test @@ -105,7 +104,7 @@ void createUsers_shouldThrowErrorIfLoggedInUserIsNotOkrChampion() { when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(new AuthorizationUser(loggedInUser)); assertThrows(OkrResponseStatusException.class, - () -> userAuthorizationService.createUsers(List.of(user, user2))); + () -> userAuthorizationService.createUsers(List.of(user, user2))); } @DisplayName("isUserMemberOfTeams() should return false if user is not member of teams") diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserUpdateHelperTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserUpdateHelperTest.java index 958eaac311..504c8ee5c6 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserUpdateHelperTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserUpdateHelperTest.java @@ -1,13 +1,13 @@ package ch.puzzle.okr.service.authorization; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.models.User; import ch.puzzle.okr.multitenancy.TenantConfigProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - public class UserUpdateHelperTest { private AuthorizationRegistrationService.UserUpdateHelper helper; @@ -20,14 +20,16 @@ void setup() { @Test void updateUserFromWithTokenData() { // arrange - User userFromDB = User.Builder.builder() // + User userFromDB = User.Builder + .builder() // .withId(23L) // .withFirstname("firstname_from_db") // .withLastname("lastname_from_db") // .withEmail("a@b.ch") // .build(); - User userFromToken = User.Builder.builder() // + User userFromToken = User.Builder + .builder() // .withFirstname("firstname_from_token") // .withLastname("lastname_from_token") // .build(); @@ -47,7 +49,12 @@ void updateUserAsNoChampion() { // arrange User noChampionUser = User.Builder.builder().withEmail("no@champions.ch").build(); TenantConfigProvider.TenantConfig tenantConfig = new TenantConfigProvider.TenantConfig(null, // - new String[] { "yes@champions.ch" }, null, null, null, null); + new String[]{ + "yes@champions.ch" }, + null, + null, + null, + null); // act User updatedUser = helper.setOkrChampionFromProperties(noChampionUser, tenantConfig); @@ -61,7 +68,12 @@ void updateUserAsChampion() { // arrange User championUser = User.Builder.builder().withEmail("yes@champions.ch").build(); TenantConfigProvider.TenantConfig tenantConfig = new TenantConfigProvider.TenantConfig(null, // - new String[] { "yes@champions.ch" }, null, null, null, null); + new String[]{ + "yes@champions.ch" }, + null, + null, + null, + null); // act User updatedUser = helper.setOkrChampionFromProperties(championUser, tenantConfig); diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/ActionBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/ActionBusinessServiceTest.java index 41e8151e4c..b1acd4babd 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/ActionBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/ActionBusinessServiceTest.java @@ -1,5 +1,11 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.Unit; import ch.puzzle.okr.models.authorization.AuthorizationUser; @@ -7,20 +13,13 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.persistence.ActionPersistenceService; import ch.puzzle.okr.service.validation.ActionValidationService; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class ActionBusinessServiceTest { private static final AuthorizationUser authorizationUser = defaultAuthorizationUser(); @@ -32,12 +31,30 @@ class ActionBusinessServiceTest { @InjectMocks private ActionBusinessService actionBusinessService; - private KeyResult metricKeyResult = KeyResultMetric.Builder.builder().withBaseline(10D).withStretchGoal(50D) - .withUnit(Unit.CHF).withId(8L).withTitle("Keyresult Metric").build(); - private Action action1 = Action.Builder.builder().withId(1L).withAction("Neue Katze").withIsChecked(false) - .withPriority(0).withKeyResult(metricKeyResult).build(); - private Action action2 = Action.Builder.builder().withId(2L).withAction("Neues Lama").withIsChecked(true) - .withPriority(1).withKeyResult(metricKeyResult).build(); + private KeyResult metricKeyResult = KeyResultMetric.Builder + .builder() + .withBaseline(10D) + .withStretchGoal(50D) + .withUnit(Unit.CHF) + .withId(8L) + .withTitle("Keyresult Metric") + .build(); + private Action action1 = Action.Builder + .builder() + .withId(1L) + .withAction("Neue Katze") + .withIsChecked(false) + .withPriority(0) + .withKeyResult(metricKeyResult) + .build(); + private Action action2 = Action.Builder + .builder() + .withId(2L) + .withAction("Neues Lama") + .withIsChecked(true) + .withPriority(1) + .withKeyResult(metricKeyResult) + .build(); private List actionList = List.of(action1, action2); @Test @@ -78,8 +95,13 @@ void shouldUpdateMultipleActionsNoKeyResult() { @Test void shouldCreateActionWhenUpdateWithNoId() { - Action action = Action.Builder.builder().withAction("Neue Katze").withPriority(0).withIsChecked(false) - .withKeyResult(metricKeyResult).build(); + Action action = Action.Builder + .builder() + .withAction("Neue Katze") + .withPriority(0) + .withIsChecked(false) + .withKeyResult(metricKeyResult) + .build(); actionBusinessService.updateEntities(List.of(action)); verify(actionPersistenceService, times(1)).save(action); @@ -95,10 +117,20 @@ void shouldUpdateMultipleActionsNormal() { @Test void shouldCreateMultipleActions() { - Action newAction1 = Action.Builder.builder().withAction("Neuer Drucker").withKeyResult(metricKeyResult) - .withPriority(0).withIsChecked(false).build(); - Action newAction2 = Action.Builder.builder().withAction("Neues Papier").withKeyResult(metricKeyResult) - .withPriority(1).withIsChecked(false).build(); + Action newAction1 = Action.Builder + .builder() + .withAction("Neuer Drucker") + .withKeyResult(metricKeyResult) + .withPriority(0) + .withIsChecked(false) + .build(); + Action newAction2 = Action.Builder + .builder() + .withAction("Neues Papier") + .withKeyResult(metricKeyResult) + .withPriority(1) + .withIsChecked(false) + .build(); when(actionPersistenceService.save(newAction1)).thenReturn(action1); when(actionPersistenceService.save(newAction2)).thenReturn(action2); @@ -112,8 +144,13 @@ void shouldCreateMultipleActions() { @Test void shouldCreateOneAction() { - Action newAction1 = Action.Builder.builder().withAction("Neuer Drucker").withKeyResult(metricKeyResult) - .withPriority(0).withIsChecked(false).build(); + Action newAction1 = Action.Builder + .builder() + .withAction("Neuer Drucker") + .withKeyResult(metricKeyResult) + .withPriority(0) + .withIsChecked(false) + .build(); when(actionPersistenceService.save(newAction1)).thenReturn(action1); List createdActions = actionBusinessService.createEntities(List.of(newAction1)); diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentBusinessServiceTest.java index 66277c8f3c..f956707a2e 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentBusinessServiceTest.java @@ -1,5 +1,15 @@ package ch.puzzle.okr.service.business; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.alignment.Alignment; import ch.puzzle.okr.models.alignment.KeyResultAlignment; @@ -7,6 +17,9 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.persistence.AlignmentPersistenceService; import ch.puzzle.okr.service.validation.AlignmentValidationService; +import java.util.ArrayList; +import java.util.List; +import javax.swing.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -16,21 +29,6 @@ import org.springframework.http.HttpStatus; import org.springframework.test.context.bean.override.mockito.MockitoBean; -import javax.swing.*; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class AlignmentBusinessServiceTest { @MockitoBean @@ -46,8 +44,13 @@ class AlignmentBusinessServiceTest { @BeforeEach void setUp() { - this.keyResult = KeyResultMetric.Builder.builder().withId(1L).withBaseline(10.0) - .withDescription("Awesome Keyresult").withStretchGoal(100.0).build(); + this.keyResult = KeyResultMetric.Builder + .builder() + .withId(1L) + .withBaseline(10.0) + .withDescription("Awesome Keyresult") + .withStretchGoal(100.0) + .build(); this.alignments = new ArrayList<>(); this.alignments.add(KeyResultAlignment.Builder.builder().withId(12L).withTargetKeyResult(keyResult).build()); @@ -58,10 +61,11 @@ void setUp() { @Test void updateEntityShouldThrowExceptionWhenValidationFails() { doThrow(new OkrResponseStatusException(HttpStatus.BAD_REQUEST, "Error Message")) - .when(alignmentValidationService).validateOnUpdate(eq(1L), any(KeyResultAlignment.class)); + .when(alignmentValidationService) + .validateOnUpdate(eq(1L), any(KeyResultAlignment.class)); assertThrows(OkrResponseStatusException.class, - () -> alignmentBusinessService.updateEntity(1L, new KeyResultAlignment())); + () -> alignmentBusinessService.updateEntity(1L, new KeyResultAlignment())); } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessServiceTest.java index 29b57b5aed..198c69e0fc 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/AlignmentSelectionBusinessServiceTest.java @@ -1,20 +1,19 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.models.alignment.AlignmentSelectionId; import ch.puzzle.okr.service.persistence.AlignmentSelectionPersistenceService; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static ch.puzzle.okr.test.TestConstants.TEAM_PUZZLE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class AlignmentSelectionBusinessServiceTest { @@ -24,9 +23,16 @@ class AlignmentSelectionBusinessServiceTest { AlignmentSelectionPersistenceService alignmentSelectionPersistenceService; private static AlignmentSelection createAlignmentSelection() { - return AlignmentSelection.Builder.builder().withAlignmentSelectionId(AlignmentSelectionId.of(9L, 15L)) - .withTeamId(5L).withTeamName(TEAM_PUZZLE).withObjectiveTitle("Objective 9").withQuarterId(2L) - .withQuarterLabel("GJ 23/24-Q1").withKeyResultTitle("Key Result 15").build(); + return AlignmentSelection.Builder + .builder() + .withAlignmentSelectionId(AlignmentSelectionId.of(9L, 15L)) + .withTeamId(5L) + .withTeamName(TEAM_PUZZLE) + .withObjectiveTitle("Objective 9") + .withQuarterId(2L) + .withQuarterLabel("GJ 23/24-Q1") + .withKeyResultTitle("Key Result 15") + .build(); } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/CheckInBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/CheckInBusinessServiceTest.java index 9a6d397863..fc4c173710 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/CheckInBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/CheckInBusinessServiceTest.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Unit; import ch.puzzle.okr.models.User; import ch.puzzle.okr.models.authorization.AuthorizationUser; @@ -18,11 +23,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class CheckInBusinessServiceTest { private static final AuthorizationUser authorizationUser = defaultAuthorizationUser(); @@ -36,18 +36,46 @@ class CheckInBusinessServiceTest { @InjectMocks private CheckInBusinessService checkInBusinessService; - private User user = User.Builder.builder().withEmail("Email").withFirstname("Firstname").withLastname("Lastname") + private User user = User.Builder + .builder() + .withEmail("Email") + .withFirstname("Firstname") + .withLastname("Lastname") + .build(); + private KeyResult ordinalKeyResult = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Baum") + .withStretchZone("Wald") + .withId(7L) + .withTitle("Keyresult Ordinal") + .build(); + private KeyResult metricKeyResult = KeyResultMetric.Builder + .builder() + .withBaseline(10D) + .withStretchGoal(50D) + .withUnit(Unit.CHF) + .withId(8L) + .withTitle("Keyresult Metric") + .build(); + private CheckIn checkInMetric = CheckInMetric.Builder + .builder() + .withValue(30D) + .withId(1L) + .withConfidence(5) + .withChangeInfo("ChangeInfo1") + .withInitiatives("Initiatives1") + .withCreatedBy(user) + .withKeyResult(metricKeyResult) + .build(); + private CheckIn checkInOrdinal = CheckInOrdinal.Builder + .builder() + .withZone(Zone.COMMIT) + .withConfidence(5) + .withChangeInfo("ChangeInfo2") + .withInitiatives("Initiatives2") + .withCreatedBy(user) + .withKeyResult(ordinalKeyResult) .build(); - private KeyResult ordinalKeyResult = KeyResultOrdinal.Builder.builder().withCommitZone("Baum") - .withStretchZone("Wald").withId(7L).withTitle("Keyresult Ordinal").build(); - private KeyResult metricKeyResult = KeyResultMetric.Builder.builder().withBaseline(10D).withStretchGoal(50D) - .withUnit(Unit.CHF).withId(8L).withTitle("Keyresult Metric").build(); - private CheckIn checkInMetric = CheckInMetric.Builder.builder().withValue(30D).withId(1L).withConfidence(5) - .withChangeInfo("ChangeInfo1").withInitiatives("Initiatives1").withCreatedBy(user) - .withKeyResult(metricKeyResult).build(); - private CheckIn checkInOrdinal = CheckInOrdinal.Builder.builder().withZone(Zone.COMMIT).withConfidence(5) - .withChangeInfo("ChangeInfo2").withInitiatives("Initiatives2").withCreatedBy(user) - .withKeyResult(ordinalKeyResult).build(); @Test void shouldGetMetricCheckIn() { diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/CompletedBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/CompletedBusinessServiceTest.java index 0302b92e97..addeb95a4e 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/CompletedBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/CompletedBusinessServiceTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.service.business; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Completed; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.service.persistence.CompletedPersistenceService; @@ -12,10 +16,6 @@ import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class CompletedBusinessServiceTest { @Mock @@ -23,9 +23,12 @@ class CompletedBusinessServiceTest { @Mock CompletedValidationService validator; - Completed successfulCompleted = Completed.Builder.builder().withId(1L) + Completed successfulCompleted = Completed.Builder + .builder() + .withId(1L) .withObjective(Objective.Builder.builder().withId(3L).withTitle("Gute Lernende").build()) - .withComment("Wir haben es gut geschafft").build(); + .withComment("Wir haben es gut geschafft") + .build(); @InjectMocks @Spy @@ -35,10 +38,15 @@ class CompletedBusinessServiceTest { void saveSuccessFulCompleted() { Mockito.when(completedPersistenceService.save(any())).thenReturn(successfulCompleted); - Completed completed = Completed.Builder.builder() - .withObjective(Objective.Builder.builder().withId(4L) - .withTitle("Build a company culture that kills the competition.").build()) - .withComment("Das ist gut").build(); + Completed completed = Completed.Builder + .builder() + .withObjective(Objective.Builder + .builder() + .withId(4L) + .withTitle("Build a company culture that kills the competition.") + .build()) + .withComment("Das ist gut") + .build(); Completed savedCompleted = completedBusinessService.createCompleted(completed); verify(completedPersistenceService, times(1)).save(completed); @@ -47,8 +55,14 @@ void saveSuccessFulCompleted() { @Test void shouldBePossibleToSaveCompletedWithoutComment() { - Completed completed = Completed.Builder.builder().withObjective(Objective.Builder.builder().withId(4L) - .withTitle("Build a company culture that kills the competition.").build()).build(); + Completed completed = Completed.Builder + .builder() + .withObjective(Objective.Builder + .builder() + .withId(4L) + .withTitle("Build a company culture that kills the competition.") + .build()) + .build(); Mockito.when(completedPersistenceService.save(any())).thenReturn(successfulCompleted); diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceIT.java index 13e46094a9..7cbb680aa1 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceIT.java @@ -1,6 +1,12 @@ package ch.puzzle.okr.service.business; -import ch.puzzle.okr.test.TestHelper; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.Unit; @@ -17,6 +23,9 @@ import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.service.authorization.AuthorizationService; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,16 +33,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; -import java.util.List; - -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.when; - @SpringIntegrationTest class KeyResultBusinessServiceIT { private static final String KEY_RESULT_UPDATED = "Updated Key Result"; @@ -56,19 +55,32 @@ class KeyResultBusinessServiceIT { private AuthorizationService authorizationService; private static KeyResult createKeyResultMetric(Long id) { - return KeyResultMetric.Builder.builder().withBaseline(3.0).withStretchGoal(5.0).withUnit(Unit.FTE).withId(id) - .withTitle("Title").withCreatedBy(User.Builder.builder().withId(1L).build()) + return KeyResultMetric.Builder + .builder() + .withBaseline(3.0) + .withStretchGoal(5.0) + .withUnit(Unit.FTE) + .withId(id) + .withTitle("Title") + .withCreatedBy(User.Builder.builder().withId(1L).build()) .withOwner(User.Builder.builder().withId(1L).build()) - .withObjective(Objective.Builder.builder().withId(4L).build()).withCreatedOn(LocalDateTime.now()) + .withObjective(Objective.Builder.builder().withId(4L).build()) + .withCreatedOn(LocalDateTime.now()) .build(); } private static KeyResult createKeyResultOrdinal(Long id) { - return KeyResultOrdinal.Builder.builder().withCommitZone("Hamster").withTargetZone("Katze").withId(id) - .withTitle("Ordinal KeyResult").withStretchZone("ZOO") + return KeyResultOrdinal.Builder + .builder() + .withCommitZone("Hamster") + .withTargetZone("Katze") + .withId(id) + .withTitle("Ordinal KeyResult") + .withStretchZone("ZOO") .withCreatedBy(User.Builder.builder().withId(1L).build()) .withOwner(User.Builder.builder().withId(1L).build()) - .withObjective(Objective.Builder.builder().withId(4L).build()).withCreatedOn(LocalDateTime.now()) + .withObjective(Objective.Builder.builder().withId(4L).build()) + .withCreatedOn(LocalDateTime.now()) .build(); } @@ -77,18 +89,32 @@ private static CheckIn createCheckInMetric(KeyResult keyResult) { } private static CheckIn createCheckInOrdinal(KeyResult keyResult) { - return CheckInOrdinal.Builder.builder().withKeyResult(keyResult).withConfidence(5).withZone(Zone.COMMIT) + return CheckInOrdinal.Builder + .builder() + .withKeyResult(keyResult) + .withConfidence(5) + .withZone(Zone.COMMIT) .build(); } private static Action createAction1(KeyResult keyResult) { - return Action.Builder.builder().withIsChecked(false).withAction("Neuer Drucker").withPriority(0) - .withKeyResult(keyResult).build(); + return Action.Builder + .builder() + .withIsChecked(false) + .withAction("Neuer Drucker") + .withPriority(0) + .withKeyResult(keyResult) + .build(); } private static Action createAction2(KeyResult keyResult) { - return Action.Builder.builder().withIsChecked(false).withAction("Neues Papier").withPriority(0) - .withKeyResult(keyResult).build(); + return Action.Builder + .builder() + .withIsChecked(false) + .withAction("Neues Papier") + .withPriority(0) + .withKeyResult(keyResult) + .build(); } @BeforeEach @@ -134,8 +160,8 @@ void updateEntitiesShouldUpdateKeyResultWithSameTypeMetric() { createdKeyResult = keyResultBusinessService.createEntity(createKeyResultMetric(null), authorizationUser); createdKeyResult.setTitle(KEY_RESULT_UPDATED); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(createdKeyResult.getId(), - createdKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(createdKeyResult.getId(), createdKeyResult, List.of()); assertSameKeyResult(createdKeyResult, updatedKeyResult.keyResult()); } @@ -147,8 +173,8 @@ void updateEntitiesShouldUpdateKeyResultWithSameTypeMetricWithActionList() { action1 = actionBusinessService.createEntity(createAction1(createdKeyResult)); action2 = actionBusinessService.createEntity(createAction2(createdKeyResult)); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(createdKeyResult.getId(), - createdKeyResult, List.of(action1, action2)); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(createdKeyResult.getId(), createdKeyResult, List.of(action1, action2)); assertSameKeyResult(createdKeyResult, updatedKeyResult.keyResult()); assertSameActions(List.of(action1, action2), updatedKeyResult); @@ -159,21 +185,21 @@ void updateEntitiesShouldUpdateKeyResultWithSameTypeOrdinal() { createdKeyResult = keyResultBusinessService.createEntity(createKeyResultOrdinal(null), authorizationUser); createdKeyResult.setTitle(KEY_RESULT_UPDATED); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(createdKeyResult.getId(), - createdKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(createdKeyResult.getId(), createdKeyResult, List.of()); assertSameKeyResult(createdKeyResult, updatedKeyResult.keyResult()); } @Test void updateEntitiesShouldRecreateKeyResultMetric() { - KeyResult savedKeyResult = keyResultBusinessService.createEntity(createKeyResultOrdinal(null), - authorizationUser); + KeyResult savedKeyResult = keyResultBusinessService + .createEntity(createKeyResultOrdinal(null), authorizationUser); Long createdKeyResultId = savedKeyResult.getId(); KeyResult changedKeyResult = createKeyResultMetric(savedKeyResult.getId()); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of()); createdKeyResult = updatedKeyResult.keyResult(); assertRecreatedKeyResult(updatedKeyResult.keyResult(), createdKeyResultId); @@ -181,15 +207,15 @@ void updateEntitiesShouldRecreateKeyResultMetric() { @Test void updateEntitiesShouldRecreateKeyResultMetricWithActionList() { - KeyResult savedKeyResult = keyResultBusinessService.createEntity(createKeyResultOrdinal(null), - authorizationUser); + KeyResult savedKeyResult = keyResultBusinessService + .createEntity(createKeyResultOrdinal(null), authorizationUser); action1 = actionBusinessService.createEntity(createAction1(savedKeyResult)); action2 = actionBusinessService.createEntity(createAction2(savedKeyResult)); KeyResult changedKeyResult = createKeyResultMetric(savedKeyResult.getId()); Long createdKeyResultId = changedKeyResult.getId(); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of(action1, action2)); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of(action1, action2)); createdKeyResult = updatedKeyResult.keyResult(); assertRecreatedKeyResult(updatedKeyResult.keyResult(), createdKeyResultId); @@ -198,13 +224,13 @@ void updateEntitiesShouldRecreateKeyResultMetricWithActionList() { @Test void updateEntitiesShouldRecreateKeyResultOrdinal() { - KeyResult savedKeyResult = keyResultBusinessService.createEntity(createKeyResultMetric(null), - authorizationUser); + KeyResult savedKeyResult = keyResultBusinessService + .createEntity(createKeyResultMetric(null), authorizationUser); Long createdKeyResultId = savedKeyResult.getId(); KeyResult changedKeyResult = createKeyResultOrdinal(savedKeyResult.getId()); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of()); createdKeyResult = updatedKeyResult.keyResult(); assertRecreatedKeyResult(updatedKeyResult.keyResult(), createdKeyResultId); @@ -217,8 +243,8 @@ void updateEntitiesShouldUpdateKeyResultWithDifferentTypeAndCheckInMetric() { KeyResult changedKeyResult = createKeyResultMetric(createdKeyResult.getId()); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of()); assertUpdatedKeyResult(changedKeyResult, updatedKeyResult.keyResult()); } @@ -234,8 +260,8 @@ void updateEntitiesShouldUpdateKeyResultWithDifferentTypeAndCheckInMetricWithAct action1.setChecked(true); action2.setChecked(true); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of(action1, action2)); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of(action1, action2)); assertUpdatedKeyResult(changedKeyResult, updatedKeyResult.keyResult()); assertUpdatedActions(List.of(action1, action2), updatedKeyResult); @@ -248,8 +274,8 @@ void updateEntitiesShouldUpdateKeyResultWithDifferentTypeAndCheckInOrdinal() { KeyResult changedKeyResult = createKeyResultOrdinal(createdKeyResult.getId()); - KeyResultWithActionList updatedKeyResult = keyResultBusinessService.updateEntities(changedKeyResult.getId(), - changedKeyResult, List.of()); + KeyResultWithActionList updatedKeyResult = keyResultBusinessService + .updateEntities(changedKeyResult.getId(), changedKeyResult, List.of()); assertUpdatedKeyResult(changedKeyResult, updatedKeyResult.keyResult()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceTest.java index 03ad68583e..fe99ce8108 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/KeyResultBusinessServiceTest.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.User; @@ -12,6 +17,8 @@ import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; import ch.puzzle.okr.service.validation.KeyResultValidationService; +import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -22,14 +29,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.Collections; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class KeyResultBusinessServiceTest { private static final AuthorizationUser authorizationUser = defaultAuthorizationUser(); @@ -63,21 +62,55 @@ void setup() { objective = Objective.Builder.builder().withId(5L).withTitle("Objective 1").build(); - metricKeyResult = KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(7.0).withId(5L) - .withTitle("Keyresult Metric").withObjective(objective).withOwner(user).withCreatedBy(user).build(); - ordinalKeyResult = KeyResultOrdinal.Builder.builder().withCommitZone("Baum").withStretchZone("Wald").withId(7L) - .withTitle("Keyresult Ordinal").withObjective(objective).withOwner(user).withCreatedBy(user).build(); + metricKeyResult = KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(7.0) + .withId(5L) + .withTitle("Keyresult Metric") + .withObjective(objective) + .withOwner(user) + .withCreatedBy(user) + .build(); + ordinalKeyResult = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Baum") + .withStretchZone("Wald") + .withId(7L) + .withTitle("Keyresult Ordinal") + .withObjective(objective) + .withOwner(user) + .withCreatedBy(user) + .build(); - checkIn1 = CheckInMetric.Builder.builder().withId(1L).withKeyResult(metricKeyResult).withCreatedBy(user) + checkIn1 = CheckInMetric.Builder + .builder() + .withId(1L) + .withKeyResult(metricKeyResult) + .withCreatedBy(user) .build(); - checkIn2 = CheckInOrdinal.Builder.builder().withId(2L).withKeyResult(ordinalKeyResult).withCreatedBy(user) + checkIn2 = CheckInOrdinal.Builder + .builder() + .withId(2L) + .withKeyResult(ordinalKeyResult) + .withCreatedBy(user) .build(); - checkIn3 = CheckInOrdinal.Builder.builder().withId(3L).withKeyResult(ordinalKeyResult).withCreatedBy(user) + checkIn3 = CheckInOrdinal.Builder + .builder() + .withId(3L) + .withKeyResult(ordinalKeyResult) + .withCreatedBy(user) .build(); keyResults = List.of(metricKeyResult, ordinalKeyResult); checkIns = List.of(checkIn1, checkIn2, checkIn3); - Action action = Action.Builder.builder().withId(3L).withAction("Neues Haus").withPriority(1).withIsChecked(true) - .withKeyResult(metricKeyResult).build(); + Action action = Action.Builder + .builder() + .withId(3L) + .withAction("Neues Haus") + .withPriority(1) + .withIsChecked(true) + .withKeyResult(metricKeyResult) + .build(); actions = List.of(action, action); } @@ -101,8 +134,11 @@ void shouldGetOrdinalKeyResultById() { @Test void shouldThrowExceptionWhenDefaultMethodUsed() { - IllegalCallerException exception = assertThrows(IllegalCallerException.class, () -> keyResultBusinessService - .updateEntity(metricKeyResult.getId(), metricKeyResult, authorizationUser)); + IllegalCallerException exception = assertThrows(IllegalCallerException.class, + () -> keyResultBusinessService + .updateEntity(metricKeyResult.getId(), + metricKeyResult, + authorizationUser)); assertEquals("unsupported method 'updateEntity' use updateEntities() instead", exception.getMessage()); } @@ -110,8 +146,11 @@ void shouldThrowExceptionWhenDefaultMethodUsed() { @Test void shouldEditMetricKeyResultWhenNoTypeChange() { List emptyList = Collections.emptyList(); - KeyResult newKeyresult = spy( - KeyResultMetric.Builder.builder().withId(1L).withTitle("Keyresult Metric update").build()); + KeyResult newKeyresult = spy(KeyResultMetric.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Metric update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(metricKeyResult); Mockito.when(keyResultPersistenceService.updateEntity(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setModifiedOn(any()); @@ -127,8 +166,11 @@ void shouldEditMetricKeyResultWhenNoTypeChange() { @Test void shouldEditOrdinalKeyResultWhenNoTypeChange() { List emptyList = Collections.emptyList(); - KeyResult newKeyresult = spy( - KeyResultOrdinal.Builder.builder().withId(1L).withTitle("Keyresult Ordinal update").build()); + KeyResult newKeyresult = spy(KeyResultOrdinal.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Ordinal update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(ordinalKeyResult); Mockito.when(keyResultPersistenceService.updateEntity(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setModifiedOn(any()); @@ -144,8 +186,11 @@ void shouldEditOrdinalKeyResultWhenNoTypeChange() { @Test void shouldEditMetricKeyResultWhenATypeChange() { List emptyList = Collections.emptyList(); - KeyResult newKeyresult = spy( - KeyResultMetric.Builder.builder().withId(1L).withTitle("Keyresult Metric update").build()); + KeyResult newKeyresult = spy(KeyResultMetric.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Metric update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(ordinalKeyResult); Mockito.when(keyResultPersistenceService.recreateEntity(any(), any())).thenReturn(newKeyresult); Mockito.when(checkInBusinessService.getCheckInsByKeyResultId(any())).thenReturn(emptyList); @@ -164,8 +209,11 @@ void shouldEditMetricKeyResultWhenATypeChange() { @Test void shouldEditOrdinalKeyResultWhenATypeChange() { List emptyList = Collections.emptyList(); - KeyResult newKeyresult = spy( - KeyResultOrdinal.Builder.builder().withId(1L).withTitle("Keyresult Ordinal update").build()); + KeyResult newKeyresult = spy(KeyResultOrdinal.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Ordinal update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(metricKeyResult); Mockito.when(keyResultPersistenceService.recreateEntity(any(), any())).thenReturn(newKeyresult); Mockito.when(checkInBusinessService.getCheckInsByKeyResultId(any())).thenReturn(emptyList); @@ -183,8 +231,11 @@ void shouldEditOrdinalKeyResultWhenATypeChange() { @Test void shouldOnlyEditCoupleOfAttributesFromMetricKeyResultWhenATypeChangeAndCheckIns() { List emptyList = checkIns; - KeyResult newKeyresult = spy( - KeyResultMetric.Builder.builder().withId(1L).withTitle("Keyresult Metric update").build()); + KeyResult newKeyresult = spy(KeyResultMetric.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Metric update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(ordinalKeyResult); Mockito.when(keyResultPersistenceService.updateEntity(any())).thenReturn(newKeyresult); Mockito.when(checkInBusinessService.getCheckInsByKeyResultId(any())).thenReturn(emptyList); @@ -201,8 +252,11 @@ void shouldOnlyEditCoupleOfAttributesFromMetricKeyResultWhenATypeChangeAndCheckI @Test void shouldOnlyEditCoupleOfAttributesFromOrdinalKeyResultWhenATypeChangeAndCheckIns() { List emptyList = checkIns; - KeyResult newKeyresult = spy( - KeyResultOrdinal.Builder.builder().withId(1L).withTitle("Keyresult Ordinal update").build()); + KeyResult newKeyresult = spy(KeyResultOrdinal.Builder + .builder() + .withId(1L) + .withTitle("Keyresult Ordinal update") + .build()); Mockito.when(keyResultPersistenceService.findById(1L)).thenReturn(metricKeyResult); Mockito.when(keyResultPersistenceService.updateEntity(any())).thenReturn(newKeyresult); Mockito.when(checkInBusinessService.getCheckInsByKeyResultId(any())).thenReturn(emptyList); @@ -218,8 +272,14 @@ void shouldOnlyEditCoupleOfAttributesFromOrdinalKeyResultWhenATypeChangeAndCheck @Test void saveMetricKeyResult() { - KeyResult newKeyresult = spy(KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(8.0).withId(1L) - .withTitle("Keyresult Metric save").withDescription("The description").build()); + KeyResult newKeyresult = spy(KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(8.0) + .withId(1L) + .withTitle("Keyresult Metric save") + .withDescription("The description") + .build()); Mockito.when(keyResultPersistenceService.save(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setCreatedOn(any()); @@ -230,9 +290,14 @@ void saveMetricKeyResult() { @Test void saveOrdinalKeyResult() { - KeyResult newKeyresult = spy( - KeyResultOrdinal.Builder.builder().withCommitZone("Eine Pflanze").withTargetZone("Ein Baum").withId(1L) - .withTitle("Keyresult ordinal save").withDescription("The description").build()); + KeyResult newKeyresult = spy(KeyResultOrdinal.Builder + .builder() + .withCommitZone("Eine Pflanze") + .withTargetZone("Ein Baum") + .withId(1L) + .withTitle("Keyresult ordinal save") + .withDescription("The description") + .build()); Mockito.when(keyResultPersistenceService.save(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setCreatedOn(any()); @@ -243,8 +308,13 @@ void saveOrdinalKeyResult() { @Test void shouldBePossibleToSaveMetricKeyResultWithoutDescription() { - KeyResult newKeyresult = spy(KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(8.0).withId(1L) - .withTitle("Keyresult Metric save").build()); + KeyResult newKeyresult = spy(KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(8.0) + .withId(1L) + .withTitle("Keyresult Metric save") + .build()); Mockito.when(keyResultPersistenceService.save(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setCreatedOn(any()); @@ -255,8 +325,13 @@ void shouldBePossibleToSaveMetricKeyResultWithoutDescription() { @Test void shouldBePossibleToSaveOrdinalKeyResultWithoutDescription() { - KeyResult newKeyresult = spy(KeyResultOrdinal.Builder.builder().withCommitZone("Eine Pflanze") - .withTargetZone("Ein Baum").withId(1L).withTitle("Keyresult ordinal save").build()); + KeyResult newKeyresult = spy(KeyResultOrdinal.Builder + .builder() + .withCommitZone("Eine Pflanze") + .withTargetZone("Ein Baum") + .withId(1L) + .withTitle("Keyresult ordinal save") + .build()); Mockito.when(keyResultPersistenceService.save(any())).thenReturn(newKeyresult); doNothing().when(newKeyresult).setCreatedOn(any()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/ObjectiveBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/ObjectiveBusinessServiceTest.java index 97c32e483d..fe9d31d235 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/ObjectiveBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/ObjectiveBusinessServiceTest.java @@ -1,5 +1,13 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.models.State.DRAFT; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.NOT_FOUND; + import ch.puzzle.okr.models.*; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.keyresult.KeyResult; @@ -7,6 +15,9 @@ import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.service.validation.ObjectiveValidationService; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -18,19 +29,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static ch.puzzle.okr.models.State.DRAFT; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.NOT_FOUND; - @ExtendWith(MockitoExtension.class) class ObjectiveBusinessServiceTest { private static final AuthorizationUser authorizationUser = defaultAuthorizationUser(); @@ -48,14 +46,31 @@ class ObjectiveBusinessServiceTest { private final Team team1 = Team.Builder.builder().withId(1L).withName("Team1").build(); private final Quarter quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build(); - private final User user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + private final User user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); private final Objective objective = Objective.Builder.builder().withId(5L).withTitle("Objective 1").build(); - private final Objective fullObjective = Objective.Builder.builder().withTitle("FullObjective1").withCreatedBy(user) - .withTeam(team1).withQuarter(quarter).withDescription("This is our description") - .withModifiedOn(LocalDateTime.MAX).build(); - private final KeyResult ordinalKeyResult = KeyResultOrdinal.Builder.builder().withCommitZone("Baum") - .withStretchZone("Wald").withId(5L).withTitle("Keyresult Ordinal").withObjective(objective).build(); + private final Objective fullObjective = Objective.Builder + .builder() + .withTitle("FullObjective1") + .withCreatedBy(user) + .withTeam(team1) + .withQuarter(quarter) + .withDescription("This is our description") + .withModifiedOn(LocalDateTime.MAX) + .build(); + private final KeyResult ordinalKeyResult = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Baum") + .withStretchZone("Wald") + .withId(5L) + .withTitle("Keyresult Ordinal") + .withObjective(objective) + .build(); private final List keyResultList = List.of(ordinalKeyResult, ordinalKeyResult, ordinalKeyResult); @Test @@ -89,9 +104,16 @@ void shouldNotFindTheObjective() { @Test void shouldSaveANewObjective() { - Objective objective = spy(Objective.Builder.builder().withTitle("Received Objective").withTeam(team1) - .withQuarter(quarter).withDescription("The description").withModifiedOn(null).withModifiedBy(null) - .withState(DRAFT).build()); + Objective objective = spy(Objective.Builder + .builder() + .withTitle("Received Objective") + .withTeam(team1) + .withQuarter(quarter) + .withDescription("The description") + .withModifiedOn(null) + .withModifiedBy(null) + .withState(DRAFT) + .build()); doNothing().when(objective).setCreatedOn(any()); @@ -105,8 +127,13 @@ void shouldSaveANewObjective() { @Test void shouldNotThrowResponseStatusExceptionWhenPuttingNullId() { - Objective objective1 = Objective.Builder.builder().withId(null).withTitle("Title") - .withDescription("Description").withModifiedOn(LocalDateTime.now()).build(); + Objective objective1 = Objective.Builder + .builder() + .withId(null) + .withTitle("Title") + .withDescription("Description") + .withModifiedOn(LocalDateTime.now()) + .build(); when(objectiveBusinessService.createEntity(objective1, authorizationUser)).thenReturn(fullObjective); Objective savedObjective = objectiveBusinessService.createEntity(objective1, authorizationUser); @@ -122,14 +149,36 @@ void updateEntityShouldHandleQuarterCorrectly(boolean hasKeyResultAnyCheckIns) { String title = "Received Objective"; String description = "The description"; Quarter changedQuarter = Quarter.Builder.builder().withId(2L).withLabel("another quarter").build(); - Objective savedObjective = Objective.Builder.builder().withId(id).withTitle(title).withTeam(team1) - .withQuarter(quarter).withDescription(null).withModifiedOn(null).withModifiedBy(null).build(); - Objective changedObjective = Objective.Builder.builder().withId(id).withTitle(title).withTeam(team1) - .withQuarter(changedQuarter).withDescription(description).withModifiedOn(null).withModifiedBy(null) + Objective savedObjective = Objective.Builder + .builder() + .withId(id) + .withTitle(title) + .withTeam(team1) + .withQuarter(quarter) + .withDescription(null) + .withModifiedOn(null) + .withModifiedBy(null) + .build(); + Objective changedObjective = Objective.Builder + .builder() + .withId(id) + .withTitle(title) + .withTeam(team1) + .withQuarter(changedQuarter) + .withDescription(description) + .withModifiedOn(null) + .withModifiedBy(null) + .build(); + Objective updatedObjective = Objective.Builder + .builder() + .withId(id) + .withTitle(title) + .withTeam(team1) + .withQuarter(hasKeyResultAnyCheckIns ? quarter : changedQuarter) + .withDescription(description) + .withModifiedOn(null) + .withModifiedBy(null) .build(); - Objective updatedObjective = Objective.Builder.builder().withId(id).withTitle(title).withTeam(team1) - .withQuarter(hasKeyResultAnyCheckIns ? quarter : changedQuarter).withDescription(description) - .withModifiedOn(null).withModifiedBy(null).build(); when(objectivePersistenceService.findById(any())).thenReturn(savedObjective); when(keyResultBusinessService.getAllKeyResultsByObjective(savedObjective.getId())).thenReturn(keyResultList); @@ -137,12 +186,12 @@ void updateEntityShouldHandleQuarterCorrectly(boolean hasKeyResultAnyCheckIns) { when(objectivePersistenceService.save(changedObjective)).thenReturn(updatedObjective); boolean isImUsed = objectiveBusinessService.isImUsed(changedObjective); - Objective updatedEntity = objectiveBusinessService.updateEntity(changedObjective.getId(), changedObjective, - authorizationUser); + Objective updatedEntity = objectiveBusinessService + .updateEntity(changedObjective.getId(), changedObjective, authorizationUser); assertEquals(hasKeyResultAnyCheckIns, isImUsed); assertEquals(hasKeyResultAnyCheckIns ? savedObjective.getQuarter() : changedObjective.getQuarter(), - updatedEntity.getQuarter()); + updatedEntity.getQuarter()); assertEquals(changedObjective.getDescription(), updatedEntity.getDescription()); assertEquals(changedObjective.getTitle(), updatedEntity.getTitle()); } @@ -160,15 +209,18 @@ void shouldDeleteObjectiveAndAssociatedKeyResults() { @Test void shouldDuplicateObjective() { // arrange - Objective sourceObjective = Objective.Builder.builder() // + Objective sourceObjective = Objective.Builder + .builder() // .withId(23L) // .withTitle("Objective 1") // .build(); - KeyResult keyResultOrdinal = KeyResultOrdinal.Builder.builder() // + KeyResult keyResultOrdinal = KeyResultOrdinal.Builder + .builder() // .withTitle("Ordinal 1") // .withObjective(sourceObjective) // .build(); - KeyResult keyResultMetric = KeyResultMetric.Builder.builder() // + KeyResult keyResultMetric = KeyResultMetric.Builder + .builder() // .withTitle("Metric 1") // .withObjective(sourceObjective) // .withUnit(Unit.FTE) // @@ -179,7 +231,8 @@ void shouldDuplicateObjective() { keyResults.add(keyResultMetric); // new Objective with no KeyResults - Objective newObjective = Objective.Builder.builder() // + Objective newObjective = Objective.Builder + .builder() // .withId(42L) // .withTitle("Objective 2") // .build(); @@ -187,8 +240,8 @@ void shouldDuplicateObjective() { when(objectivePersistenceService.save(any())).thenReturn(newObjective); // act - Objective duplicatedObjective = objectiveBusinessService.duplicateObjective(sourceObjective.getId(), - newObjective, authorizationUser, keyResults); + Objective duplicatedObjective = objectiveBusinessService + .duplicateObjective(sourceObjective.getId(), newObjective, authorizationUser, keyResults); // assert assertNotEquals(sourceObjective.getId(), duplicatedObjective.getId()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/OverviewBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/OverviewBusinessServiceTest.java index 546a65df47..926211695d 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/OverviewBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/OverviewBusinessServiceTest.java @@ -1,11 +1,22 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.test.OverviewTestHelper.QUARTER_ID; +import static ch.puzzle.okr.test.OverviewTestHelper.teamIds; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.models.overview.OverviewId; import ch.puzzle.okr.service.persistence.OverviewPersistenceService; import ch.puzzle.okr.service.validation.OverviewValidationService; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -14,18 +25,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static ch.puzzle.okr.test.OverviewTestHelper.QUARTER_ID; -import static ch.puzzle.okr.test.OverviewTestHelper.teamIds; -import static ch.puzzle.okr.test.TestHelper.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class OverviewBusinessServiceTest { @@ -49,34 +48,62 @@ private static List createOverviews() { private static List createOverviews(AuthorizationUser authorizationUser) { long index = 1L; - List overviews = new ArrayList<>(List.of( - Overview.Builder.builder() + List overviews = new ArrayList<>(List + .of(Overview.Builder + .builder() .withOverviewId(OverviewId.Builder.builder().withObjectiveId(index++).withTeamId(111L).build()) - .withObjectiveTitle("Another Team Objective A").withTeamName("team-111") - .withObjectiveCreatedOn(LocalDateTime.of(2023, 10, 21, 18, 33)).build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(index++).withTeamId(222L).build()) - .withObjectiveTitle("Another Team Objective B").withTeamName("team-222") - .withObjectiveCreatedOn(LocalDateTime.of(2023, 10, 1, 8, 53)).build())); + .withObjectiveTitle("Another Team Objective A") + .withTeamName("team-111") + .withObjectiveCreatedOn(LocalDateTime.of(2023, 10, 21, 18, 33)) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(index++) + .withTeamId(222L) + .build()) + .withObjectiveTitle("Another Team Objective B") + .withTeamName("team-222") + .withObjectiveCreatedOn(LocalDateTime.of(2023, 10, 1, 8, 53)) + .build())); for (Long teamId : authorizationUser.extractTeamIds()) { overviews - .addAll((List.of( - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(index++) - .withTeamId(teamId).build()) - .withObjectiveTitle("ZZZ Objective").withTeamName("firstLevelTeam-" + teamId) - .withObjectiveCreatedOn(LocalDateTime.of(2023, 12, 10, 18, 33)).build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(index++) - .withTeamId(teamId).build()) - .withObjectiveTitle("AAA Objective").withTeamName("firstLevelTeam-" + teamId) - .withObjectiveCreatedOn(LocalDateTime.of(2023, 9, 10, 18, 33)).build(), - Overview.Builder.builder() - .withOverviewId(OverviewId.Builder.builder().withObjectiveId(index++) - .withTeamId(teamId).build()) - .withObjectiveTitle("AAA Objective").withTeamName("firstLevelTeam-" + teamId) - .withObjectiveCreatedOn(LocalDateTime.of(2023, 9, 10, 18, 33)).build()))); + .addAll((List + .of(Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(index++) + .withTeamId(teamId) + .build()) + .withObjectiveTitle("ZZZ Objective") + .withTeamName("firstLevelTeam-" + teamId) + .withObjectiveCreatedOn(LocalDateTime.of(2023, 12, 10, 18, 33)) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(index++) + .withTeamId(teamId) + .build()) + .withObjectiveTitle("AAA Objective") + .withTeamName("firstLevelTeam-" + teamId) + .withObjectiveCreatedOn(LocalDateTime.of(2023, 9, 10, 18, 33)) + .build(), + Overview.Builder + .builder() + .withOverviewId(OverviewId.Builder + .builder() + .withObjectiveId(index++) + .withTeamId(teamId) + .build()) + .withObjectiveTitle("AAA Objective") + .withTeamName("firstLevelTeam-" + teamId) + .withObjectiveCreatedOn(LocalDateTime.of(2023, 9, 10, 18, 33)) + .build()))); } return overviews; } @@ -123,50 +150,53 @@ void getFilteredOverviewShouldReturnEmptyListOfOverviewsWhenTeamIdsAreNull() { verify(overviewValidationService, times(1)).validateOnGet(QUARTER_ID, List.of()); verify(quarterBusinessService, never()).getCurrentQuarter(); verify(overviewPersistenceService, never()).getFilteredOverview(QUARTER_ID, List.of(), "", authorizationUser); - verify(overviewPersistenceService, never()).getFilteredOverview(anyLong(), anyList(), anyString(), - eq(authorizationUser)); + verify(overviewPersistenceService, never()) + .getFilteredOverview(anyLong(), anyList(), anyString(), eq(authorizationUser)); } @Test void getFilteredOverviewShouldReturnExceptionWhenQuarterIdIsNonExistent() { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)).when(overviewValidationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)) + .when(overviewValidationService) .validateOnGet(eq(QUARTER_ID), anyList()); assertThrows(ResponseStatusException.class, - () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, List.of(), "", authorizationUser)); + () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, List.of(), "", authorizationUser)); verify(quarterBusinessService, never()).getCurrentQuarter(); verify(overviewValidationService, never()).validateOnGet(QUARTER_ID, teamIds); - verify(overviewPersistenceService, never()).getFilteredOverview(anyLong(), anyList(), anyString(), - eq(authorizationUser)); + verify(overviewPersistenceService, never()) + .getFilteredOverview(anyLong(), anyList(), anyString(), eq(authorizationUser)); } @Test void getFilteredOverviewShouldReturnExceptionWhenTeamIdIsNonExistent() { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)).when(overviewValidationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)) + .when(overviewValidationService) .validateOnGet(QUARTER_ID, teamIds); assertThrows(ResponseStatusException.class, - () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, teamIds, "", authorizationUser)); + () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, teamIds, "", authorizationUser)); verify(quarterBusinessService, never()).getCurrentQuarter(); verify(overviewValidationService, never()).validateQuarter(QUARTER_ID); verify(overviewValidationService, times(1)).validateOnGet(QUARTER_ID, teamIds); - verify(overviewPersistenceService, never()).getFilteredOverview(anyLong(), anyList(), any(), - eq(authorizationUser)); + verify(overviewPersistenceService, never()) + .getFilteredOverview(anyLong(), anyList(), any(), eq(authorizationUser)); } @Test void getFilteredOverviewShouldThrowExceptionWhenTeamIdIsNonExistent() { - doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)).when(overviewValidationService) + doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND)) + .when(overviewValidationService) .validateOnGet(QUARTER_ID, teamIds); assertThrows(ResponseStatusException.class, - () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, teamIds, "", authorizationUser)); + () -> overviewBusinessService.getFilteredOverview(QUARTER_ID, teamIds, "", authorizationUser)); verify(quarterBusinessService, never()).getCurrentQuarter(); verify(overviewValidationService, times(1)).validateOnGet(QUARTER_ID, teamIds); - verify(overviewPersistenceService, never()).getFilteredOverview(anyLong(), anyList(), anyString(), - eq(authorizationUser)); + verify(overviewPersistenceService, never()) + .getFilteredOverview(anyLong(), anyList(), anyString(), eq(authorizationUser)); } @Test @@ -178,9 +208,13 @@ void getFilteredOverviewShouldReturnSortedListUserTeamsFirst() { List overviews = overviewBusinessService.getFilteredOverview(QUARTER_ID, teamIds, null, user); - assertThat(List.of(OverviewId.of(1L, 4L, null, null), OverviewId.of(1L, 5L, null, null), - OverviewId.of(1L, 3L, null, null), OverviewId.of(111L, 1L, null, null), - OverviewId.of(222L, 2L, null, null))).hasSameElementsAs(getOverviewIds(overviews)); + assertThat(List + .of(OverviewId.of(1L, 4L, null, null), + OverviewId.of(1L, 5L, null, null), + OverviewId.of(1L, 3L, null, null), + OverviewId.of(111L, 1L, null, null), + OverviewId.of(222L, 2L, null, null))) + .hasSameElementsAs(getOverviewIds(overviews)); } private List getOverviewIds(List overviews) { diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/QuarterBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/QuarterBusinessServiceTest.java index 479620ad3d..1765144005 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/QuarterBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/QuarterBusinessServiceTest.java @@ -1,8 +1,21 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; +import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.service.persistence.QuarterPersistenceService; import ch.puzzle.okr.service.validation.QuarterValidationService; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -16,20 +29,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; -import java.time.LocalDate; -import java.time.YearMonth; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; -import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class QuarterBusinessServiceTest { @Mock @@ -74,13 +73,26 @@ void shouldCallGetQuarters() { @Test void shouldGetBacklogQuarter() { - Quarter realQuarter1 = Quarter.Builder.builder().withId(1L).withLabel("GJ-22/23-Q3") - .withStartDate(LocalDate.of(2022, 4, 1)).withEndDate(LocalDate.of(2022, 7, 31)).build(); - Quarter realQuarter2 = Quarter.Builder.builder().withId(2L).withLabel("GJ-22/23-Q4") - .withStartDate(LocalDate.of(2022, 8, 1)).withEndDate(LocalDate.of(2022, 11, 30)).build(); + Quarter realQuarter1 = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ-22/23-Q3") + .withStartDate(LocalDate.of(2022, 4, 1)) + .withEndDate(LocalDate.of(2022, 7, 31)) + .build(); + Quarter realQuarter2 = Quarter.Builder + .builder() + .withId(2L) + .withLabel("GJ-22/23-Q4") + .withStartDate(LocalDate.of(2022, 8, 1)) + .withEndDate(LocalDate.of(2022, 11, 30)) + .build(); List quarterList = new ArrayList<>(Arrays.asList(realQuarter1, realQuarter2)); - Quarter backlogQuarter = Quarter.Builder.builder().withId(BACK_LOG_QUARTER_ID).withLabel(BACK_LOG_QUARTER_LABEL) + Quarter backlogQuarter = Quarter.Builder + .builder() + .withId(BACK_LOG_QUARTER_ID) + .withLabel(BACK_LOG_QUARTER_LABEL) .build(); when(quarterPersistenceService.getMostCurrentQuarters()).thenReturn(quarterList); when(quarterPersistenceService.findByLabel(BACK_LOG_QUARTER_LABEL)).thenReturn(backlogQuarter); @@ -113,18 +125,19 @@ void shouldGenerateQuarterIfLastMonth(int month) { } private static Stream generateQuarterParams() { - return Stream.of(Arguments.of(7, "GJ xx/yy-Qzz", YearMonth.of(2030, 3), "GJ 30/31-Q1"), - Arguments.of(7, "GJ xx/yy-Qzz", YearMonth.of(2030, 9), "GJ 30/31-Q3"), - Arguments.of(5, "GJ xx/yy-Qzz", YearMonth.of(2030, 4), "GJ 30/31-Q2"), - Arguments.of(1, "GJ xx-Qzz", YearMonth.of(2030, 9), "GJ 31-Q1"), - Arguments.of(1, "GJ xxxx-Qzz", YearMonth.of(2030, 6), "GJ 2030-Q4"), - Arguments.of(2, "xx-yy-xxxx-yyyy-Qzz", YearMonth.of(2030, 1), "30-31-2030-2031-Q2")); + return Stream + .of(Arguments.of(7, "GJ xx/yy-Qzz", YearMonth.of(2030, 3), "GJ 30/31-Q1"), + Arguments.of(7, "GJ xx/yy-Qzz", YearMonth.of(2030, 9), "GJ 30/31-Q3"), + Arguments.of(5, "GJ xx/yy-Qzz", YearMonth.of(2030, 4), "GJ 30/31-Q2"), + Arguments.of(1, "GJ xx-Qzz", YearMonth.of(2030, 9), "GJ 31-Q1"), + Arguments.of(1, "GJ xxxx-Qzz", YearMonth.of(2030, 6), "GJ 2030-Q4"), + Arguments.of(2, "xx-yy-xxxx-yyyy-Qzz", YearMonth.of(2030, 1), "30-31-2030-2031-Q2")); } @ParameterizedTest @MethodSource("generateQuarterParams") void shouldGenerateCorrectQuarter(int quarterStart, String quarterFormat, YearMonth currentYearMonth, - String expectedLabel) { + String expectedLabel) { ReflectionTestUtils.setField(quarterBusinessService, "quarterStart", quarterStart); ReflectionTestUtils.setField(quarterBusinessService, "quarterFormat", quarterFormat); @@ -134,8 +147,13 @@ void shouldGenerateCorrectQuarter(int quarterStart, String quarterFormat, YearMo int monthsToNextQuarterEnd = 6; LocalDate expectedEnd = currentYearMonth.plusMonths(monthsToNextQuarterEnd).atEndOfMonth(); - Quarter expectedQuarter = Quarter.Builder.builder().withId(null).withLabel(expectedLabel) - .withStartDate(expectedStart).withEndDate(expectedEnd).build(); + Quarter expectedQuarter = Quarter.Builder + .builder() + .withId(null) + .withLabel(expectedLabel) + .withStartDate(expectedStart) + .withEndDate(expectedEnd) + .build(); Mockito.when(quarterBusinessService.getCurrentYearMonth()).thenReturn(currentYearMonth); @@ -145,12 +163,31 @@ void shouldGenerateCorrectQuarter(int quarterStart, String quarterFormat, YearMo } private static Stream getQuartersParams() { - return Stream.of(Arguments.of(5, 1, 3), Arguments.of(5, 2, 4), Arguments.of(5, 3, 4), Arguments.of(5, 4, 4), - Arguments.of(5, 5, 1), Arguments.of(5, 6, 1), Arguments.of(5, 7, 1), Arguments.of(5, 8, 2), - Arguments.of(5, 9, 2), Arguments.of(5, 10, 2), Arguments.of(5, 11, 3), Arguments.of(5, 12, 3), - Arguments.of(10, 1, 2), Arguments.of(10, 2, 2), Arguments.of(10, 3, 2), Arguments.of(10, 4, 3), - Arguments.of(10, 5, 3), Arguments.of(10, 6, 3), Arguments.of(10, 7, 4), Arguments.of(10, 8, 4), - Arguments.of(10, 9, 4), Arguments.of(10, 10, 1), Arguments.of(10, 11, 1), Arguments.of(10, 12, 1)); + return Stream + .of(Arguments.of(5, 1, 3), + Arguments.of(5, 2, 4), + Arguments.of(5, 3, 4), + Arguments.of(5, 4, 4), + Arguments.of(5, 5, 1), + Arguments.of(5, 6, 1), + Arguments.of(5, 7, 1), + Arguments.of(5, 8, 2), + Arguments.of(5, 9, 2), + Arguments.of(5, 10, 2), + Arguments.of(5, 11, 3), + Arguments.of(5, 12, 3), + Arguments.of(10, 1, 2), + Arguments.of(10, 2, 2), + Arguments.of(10, 3, 2), + Arguments.of(10, 4, 3), + Arguments.of(10, 5, 3), + Arguments.of(10, 6, 3), + Arguments.of(10, 7, 4), + Arguments.of(10, 8, 4), + Arguments.of(10, 9, 4), + Arguments.of(10, 10, 1), + Arguments.of(10, 11, 1), + Arguments.of(10, 12, 1)); } @ParameterizedTest(name = "Start month={0}, current month={1} => quarter={2}") diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/TeamBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/TeamBusinessServiceTest.java index e5586543ec..b08ef58e2a 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/TeamBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/TeamBusinessServiceTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.service.business; +import static ch.puzzle.okr.models.State.DRAFT; +import static ch.puzzle.okr.models.State.SUCCESSFUL; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -12,6 +19,8 @@ import ch.puzzle.okr.service.persistence.UserPersistenceService; import ch.puzzle.okr.service.persistence.UserTeamPersistenceService; import ch.puzzle.okr.service.validation.TeamValidationService; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -21,16 +30,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.mock.mockito.MockBean; -import java.util.ArrayList; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.*; -import static ch.puzzle.okr.models.State.DRAFT; -import static ch.puzzle.okr.models.State.SUCCESSFUL; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class TeamBusinessServiceTest { @MockBean @@ -65,18 +64,44 @@ class TeamBusinessServiceTest { @BeforeEach void setUp() { this.team1 = Team.Builder.builder().withId(1L).withName("Team 1").build(); - this.team1.setUserTeamList(List.of( - UserTeam.Builder.builder().withTeam(team1).withUser(defaultUser(2L)).withTeamAdmin(true).build(), - UserTeam.Builder.builder().withTeam(team1).withUser(defaultUser(3L)).withTeamAdmin(false).build())); + this.team1 + .setUserTeamList(List + .of(UserTeam.Builder + .builder() + .withTeam(team1) + .withUser(defaultUser(2L)) + .withTeamAdmin(true) + .build(), + UserTeam.Builder + .builder() + .withTeam(team1) + .withUser(defaultUser(3L)) + .withTeamAdmin(false) + .build())); this.team2 = Team.Builder.builder().withId(2L).withName("Team 2").build(); - this.team2.setUserTeamList(List.of( - UserTeam.Builder.builder().withTeam(team2).withUser(defaultUser(4L)).withTeamAdmin(true).build(), - UserTeam.Builder.builder().withTeam(team2).withUser(defaultUser(5L)).withTeamAdmin(true).build())); + this.team2 + .setUserTeamList(List + .of(UserTeam.Builder + .builder() + .withTeam(team2) + .withUser(defaultUser(4L)) + .withTeamAdmin(true) + .build(), + UserTeam.Builder + .builder() + .withTeam(team2) + .withUser(defaultUser(5L)) + .withTeamAdmin(true) + .build())); this.team3 = Team.Builder.builder().withId(3L).withName("Team 3").build(); this.team3.setUserTeamList(List.of()); this.teamWithIdNull = Team.Builder.builder().withName("Team with id null").build(); this.objective = Objective.Builder.builder().withId(5L).withTitle("Objective 1").withState(DRAFT).build(); - this.objectiveCompleted = Objective.Builder.builder().withId(6L).withTitle("Objective 1").withState(SUCCESSFUL) + this.objectiveCompleted = Objective.Builder + .builder() + .withId(6L) + .withTitle("Objective 1") + .withState(SUCCESSFUL) .build(); this.objectiveList = List.of(objective, objective, objective, objectiveCompleted); } @@ -109,9 +134,14 @@ void getAllTeamsSortedShouldReturnSortedListUserTeamsFirst() { User user = defaultUser(13L); List userTeamList = List .of(UserTeam.Builder.builder().withUser(user).withTeam(userTeam).withId(1L).build()); - AuthorizationUser authUser = new AuthorizationUser(User.Builder.builder().withId(user.getId()) - .withFirstname(user.getFirstname()).withLastname(user.getLastname()).withEmail(user.getEmail()) - .withUserTeamList(userTeamList).build()); + AuthorizationUser authUser = new AuthorizationUser(User.Builder + .builder() + .withId(user.getId()) + .withFirstname(user.getFirstname()) + .withLastname(user.getLastname()) + .withEmail(user.getEmail()) + .withUserTeamList(userTeamList) + .build()); when(teamPersistenceService.findAll()).thenReturn(teams); List sortedList = teamBusinessService.getAllTeams(authUser); @@ -146,8 +176,9 @@ void shouldUpdateTeam() { @Test void shouldDeleteTeamAndItsObjectives() { var team = defaultTeam(1L); - team.setUserTeamList( - List.of(UserTeam.Builder.builder().withTeam(team).withUser(new User()).withId(1L).build())); + team + .setUserTeamList(List + .of(UserTeam.Builder.builder().withTeam(team).withUser(new User()).withId(1L).build())); when(objectiveBusinessService.getEntitiesByTeamId(team.getId())).thenReturn(objectiveList); when(teamPersistenceService.findById(team.getId())).thenReturn(team); @@ -192,7 +223,7 @@ void removeUserFromTeam_shouldRemoveUser() { teamBusinessService.removeUserFromTeam(team2.getId(), user.getId()); assertEquals(2, user.getUserTeamList().size()); assertEquals(user.getUserTeamList().stream().map(ut -> ut.getTeam().getId()).toList(), - List.of(team1.getId(), team3.getId())); + List.of(team1.getId(), team3.getId())); verify(cacheService, times(1)).emptyAuthorizationUsersCache(); } @@ -212,8 +243,8 @@ void removeUserFromTeam_shouldThrowExceptionWhenLastAdminShouldBeRemoved() { when(teamPersistenceService.findById(team1.getId())).thenReturn(team1); assertThrows(OkrResponseStatusException.class, - () -> teamBusinessService.removeUserFromTeam(team1.getId(), user.getId()), - ErrorKey.TRIED_TO_DELETE_LAST_ADMIN.toString()); + () -> teamBusinessService.removeUserFromTeam(team1.getId(), user.getId()), + ErrorKey.TRIED_TO_DELETE_LAST_ADMIN.toString()); } @Test @@ -235,7 +266,7 @@ void updateOrAddTeamMembership_shouldThrowExceptionIfLastAdminShouldBeRemoved() when(userPersistenceService.findById(user.getId())).thenReturn(user); assertThrows(OkrResponseStatusException.class, - () -> teamBusinessService.updateOrAddTeamMembership(team1.getId(), user.getId(), false)); + () -> teamBusinessService.updateOrAddTeamMembership(team1.getId(), user.getId(), false)); } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/business/UserBusinessServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/business/UserBusinessServiceTest.java index 70fadedb2d..f7bfb6a83c 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/business/UserBusinessServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/business/UserBusinessServiceTest.java @@ -1,11 +1,17 @@ package ch.puzzle.okr.service.business; -import ch.puzzle.okr.test.TestHelper; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; import ch.puzzle.okr.service.CacheService; import ch.puzzle.okr.service.persistence.UserPersistenceService; import ch.puzzle.okr.service.validation.UserValidationService; +import ch.puzzle.okr.test.TestHelper; +import java.util.Arrays; +import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -17,13 +23,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.Arrays; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class UserBusinessServiceTest { @Mock @@ -38,14 +37,16 @@ class UserBusinessServiceTest { @BeforeEach void setUp() { - User userAlice = User.Builder.builder() // + User userAlice = User.Builder + .builder() // .withId(2L) // .withFirstname("Alice") // .withLastname("Wunderland") // .withEmail("wunderland@puzzle.ch") // .build(); - User userBob = User.Builder.builder() // + User userBob = User.Builder + .builder() // .withId(9L) // .withFirstname("Bob") // .withLastname("Baumeister") // @@ -81,8 +82,13 @@ void shouldReturnEmptyUsers() throws ResponseStatusException { @Test void shouldReturnSingleUserWhenFindingOwnerByValidId() { - User owner = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + User owner = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); Mockito.when(userPersistenceService.findById(any())).thenReturn(owner); User returnedUser = userBusinessService.getUserById(1L); @@ -95,8 +101,13 @@ void shouldReturnSingleUserWhenFindingOwnerByValidId() { @Test void getOrCreateUserShouldReturnSingleUserWhenUserFound() { - User newUser = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + User newUser = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); Mockito.when(userPersistenceService.getOrCreateUser(any())).thenReturn(newUser); User returnedUser = userBusinessService.getOrCreateUser(newUser); @@ -109,8 +120,13 @@ void getOrCreateUserShouldReturnSingleUserWhenUserFound() { @Test void getOrCreateUserShouldReturnSavedUserWhenUserNotFound() { - User newUser = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + User newUser = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); Mockito.when(userPersistenceService.getOrCreateUser(newUser)).thenReturn(newUser); User returnedUser = userBusinessService.getOrCreateUser(newUser); @@ -123,13 +139,20 @@ void getOrCreateUserShouldReturnSavedUserWhenUserNotFound() { @Test void getOrCreateUserShouldThrowResponseStatusExceptionWhenInvalidUser() { - User newUser = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); - Mockito.doThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Not allowed to give an id")) - .when(validationService).validateOnGetOrCreate(newUser); + User newUser = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); + Mockito + .doThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Not allowed to give an id")) + .when(validationService) + .validateOnGetOrCreate(newUser); ResponseStatusException exception = assertThrows(ResponseStatusException.class, - () -> userBusinessService.getOrCreateUser(newUser)); + () -> userBusinessService.getOrCreateUser(newUser)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals("Not allowed to give an id", exception.getReason()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceIT.java index e0ba905289..119b5cb2ce 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceIT.java @@ -1,8 +1,12 @@ package ch.puzzle.okr.service.clientconfig; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + import ch.puzzle.okr.dto.ClientConfigDto; import ch.puzzle.okr.test.SpringIntegrationTest; import jakarta.persistence.EntityNotFoundException; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -10,11 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrowsExactly; - @SpringIntegrationTest @SpringBootTest() class ClientConfigServiceIT { @@ -25,7 +24,7 @@ class ClientConfigServiceIT { @ParameterizedTest @MethodSource("tenantConfigs") void getConfigBasedOnActiveEnv_validSubdomain_returnsCorrectTenantConfig(String hostname, String activeProfile, - String issuer, String clientId) { + String issuer, String clientId) { // arrange + act ClientConfigDto clientConfig = clientConfigService.getConfigBasedOnActiveEnv(hostname); @@ -37,15 +36,16 @@ void getConfigBasedOnActiveEnv_validSubdomain_returnsCorrectTenantConfig(String } private static Stream tenantConfigs() { - return Stream.of( - Arguments.of("pitc.okr.puzzle.ch", "prod", "http://localhost:8544/realms/pitc", "pitc_okr_staging"), - Arguments.of("acme.okr.puzzle.ch", "prod", "http://localhost:8544/realms/pitc", "acme_okr_staging")); + return Stream + .of(Arguments.of("pitc.okr.puzzle.ch", "prod", "http://localhost:8544/realms/pitc", "pitc_okr_staging"), + Arguments + .of("acme.okr.puzzle.ch", "prod", "http://localhost:8544/realms/pitc", "acme_okr_staging")); } @Test void getConfigBasedOnActiveEnv_invalidSubdomain_throwsException() { assertThrowsExactly(EntityNotFoundException.class, - () -> clientConfigService.getConfigBasedOnActiveEnv("foobar.okr.puzzle.ch")); + () -> clientConfigService.getConfigBasedOnActiveEnv("foobar.okr.puzzle.ch")); } @Test diff --git a/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceTest.java index 98daa385e4..2872c53151 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/clientconfig/ClientConfigServiceTest.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.service.clientconfig; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.dto.ClientConfigDto; import ch.puzzle.okr.multitenancy.TenantConfigProvider; import ch.puzzle.okr.multitenancy.customization.TenantClientCustomization; import ch.puzzle.okr.multitenancy.customization.TenantClientCustomizationProvider; import jakarta.persistence.EntityNotFoundException; +import java.util.HashMap; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import java.util.HashMap; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class ClientConfigServiceTest { @DisplayName("getConfigBasedOnActiveEnv() should be successful when tenant is configured properly") @@ -38,7 +37,7 @@ void getConfigBasedOnActiveEnvShouldBeSuccessfulWhenTenantIsConfiguredProperly(S @ParameterizedTest @CsvSource({ "pitc,pitc.okr.ch,pitc", "acme,acme-okr.ch,acme-okr" }) void getConfigBasedOnActiveEnvShouldThrowExceptionIfClientCustomizationIsNotFound(String tenant, String hostname, - String subdomain) { + String subdomain) { // arrange TenantConfigProvider.TenantConfig tenantConfig = getTenantConfig(tenant); ClientConfigService service = getClientConfig(tenantConfig, tenant); @@ -55,7 +54,7 @@ void getConfigBasedOnActiveEnvShouldThrowExceptionIfClientCustomizationIsNotFoun @ParameterizedTest @CsvSource({ "pitc,pitc.okr.ch,pitc", "acme,acme-okr.ch,acme-okr" }) void getConfigBasedOnActiveEnvShouldThrowExceptionIfClientConfigIsNotFound(String tenant, String hostname, - String subdomain) { + String subdomain) { // arrange TenantClientCustomization tenantCustomization = getTenantClientCustomization(tenant); ClientConfigService service = getClientConfig(tenantCustomization, tenant); @@ -69,7 +68,7 @@ void getConfigBasedOnActiveEnvShouldThrowExceptionIfClientConfigIsNotFound(Strin } private ClientConfigService getClientConfig(TenantConfigProvider.TenantConfig tenantConfig, - TenantClientCustomization tenantClientCustomization, String tenantId) { + TenantClientCustomization tenantClientCustomization, String tenantId) { return mockClientConfigService(tenantConfig, tenantClientCustomization, tenantId); } @@ -82,7 +81,8 @@ private ClientConfigService getClientConfig(TenantConfigProvider.TenantConfig te } private ClientConfigService mockClientConfigService(TenantConfigProvider.TenantConfig tenantConfig, - TenantClientCustomization tenantCustomization, String tenantId) { + TenantClientCustomization tenantCustomization, + String tenantId) { TenantClientCustomizationProvider tenantCustomizationProvider = mock(TenantClientCustomizationProvider.class); when(tenantCustomizationProvider.getTenantClientCustomizationsById(tenantId)) // @@ -97,23 +97,23 @@ private ClientConfigService mockClientConfigService(TenantConfigProvider.TenantC private TenantConfigProvider.TenantConfig getTenantConfig(String tenantId) { return new TenantConfigProvider.TenantConfig( // - prefix(tenantId) + "tenantId", // - new String[] {}, // - prefix(tenantId) + "jwkSetUri", // - prefix(tenantId) + "issuerUrl", // - prefix(tenantId) + "clientId", // - null); + prefix(tenantId) + "tenantId", // + new String[]{}, // + prefix(tenantId) + "jwkSetUri", // + prefix(tenantId) + "issuerUrl", // + prefix(tenantId) + "clientId", // + null); } private TenantClientCustomization getTenantClientCustomization(String tenantId) { return new TenantClientCustomization( // - prefix(tenantId) + "favicon", // - prefix(tenantId) + "logo", // - prefix(tenantId) + "triangles", // - prefix(tenantId) + "backgroundLogo", // - prefix(tenantId) + "title", // - prefix(tenantId) + "helpSiteUrl", // - new HashMap<>()); + prefix(tenantId) + "favicon", // + prefix(tenantId) + "logo", // + prefix(tenantId) + "triangles", // + prefix(tenantId) + "backgroundLogo", // + prefix(tenantId) + "title", // + prefix(tenantId) + "helpSiteUrl", // + new HashMap<>()); } private void assertClientConfigDto(ClientConfigDto clientConfigDto, String tenant) { diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/ActionPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/ActionPersistenceServiceIT.java index b8e62b6a63..4647ec9a18 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/ActionPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/ActionPersistenceServiceIT.java @@ -1,6 +1,9 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Action; @@ -8,18 +11,14 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; - @SpringIntegrationTest class ActionPersistenceServiceIT { Action createdAction; @@ -31,10 +30,20 @@ private static Action createAction(Long id) { } private static Action createAction(Long id, int version) { - return Action.Builder.builder().withId(id).withVersion(version).withAction("Neue Katze").withPriority(0) + return Action.Builder + .builder() + .withId(id) + .withVersion(version) + .withAction("Neue Katze") + .withPriority(0) .withIsChecked(false) - .withKeyResult(KeyResultMetric.Builder.builder().withBaseline(1.0).withStretchGoal(13.0).withId(8L) - .withObjective(Objective.Builder.builder().withId(1L).build()).build()) + .withKeyResult(KeyResultMetric.Builder + .builder() + .withBaseline(1.0) + .withStretchGoal(13.0) + .withId(8L) + .withObjective(Objective.Builder.builder().withId(1L).build()) + .build()) .build(); } @@ -94,7 +103,7 @@ void updateActionShouldThrowExceptionWhenAlreadyUpdated() { changedAction.setAction(UPDATED_ACTION); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> actionPersistenceService.save(changedAction)); + () -> actionPersistenceService.save(changedAction)); List expectedErrors = List.of(new ErrorDto("DATA_HAS_BEEN_UPDATED", List.of("Action"))); assertEquals(UNPROCESSABLE_ENTITY, exception.getStatusCode()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java index de38eed3a5..211c249fe2 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentPersistenceServiceIT.java @@ -1,6 +1,9 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -10,18 +13,14 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; - @SpringIntegrationTest class AlignmentPersistenceServiceIT { @Autowired @@ -29,9 +28,12 @@ class AlignmentPersistenceServiceIT { private Alignment createdAlignment; private static ObjectiveAlignment createObjectiveAlignment(Long id) { - return ObjectiveAlignment.Builder.builder().withId(id) + return ObjectiveAlignment.Builder + .builder() + .withId(id) .withAlignedObjective(Objective.Builder.builder().withId(5L).build()) - .withTargetObjective(Objective.Builder.builder().withId(4L).build()).build(); + .withTargetObjective(Objective.Builder.builder().withId(4L).build()) + .build(); } private static KeyResultAlignment createKeyResultAlignment(Long id) { @@ -39,9 +41,13 @@ private static KeyResultAlignment createKeyResultAlignment(Long id) { } private static KeyResultAlignment createKeyResultAlignment(Long id, int version) { - return KeyResultAlignment.Builder.builder().withId(id).withVersion(version) + return KeyResultAlignment.Builder + .builder() + .withId(id) + .withVersion(version) .withAlignedObjective(Objective.Builder.builder().withId(5L).build()) - .withTargetKeyResult(KeyResultMetric.Builder.builder().withId(8L).build()).build(); + .withTargetKeyResult(KeyResultMetric.Builder.builder().withId(8L).build()) + .build(); } @BeforeEach @@ -105,7 +111,7 @@ void updateAlignmentShouldThrowExceptionWhenAlreadyUpdated() { updateAlignment.setAlignedObjective(Objective.Builder.builder().withId(8L).build()); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> alignmentPersistenceService.save(updateAlignment)); + () -> alignmentPersistenceService.save(updateAlignment)); List expectedErrors = List.of(new ErrorDto("DATA_HAS_BEEN_UPDATED", List.of("Alignment"))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceServiceIT.java index 60ab85c7d9..2e790ee582 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AlignmentSelectionPersistenceServiceIT.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import ch.puzzle.okr.models.alignment.AlignmentSelection; import ch.puzzle.okr.models.alignment.AlignmentSelectionId; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - @SpringIntegrationTest class AlignmentSelectionPersistenceServiceIT { @Autowired @@ -37,8 +36,9 @@ void getAlignmentSelectionByQuarterIdAndTeamIdNotShouldReturnAlignmentSelections .getAlignmentSelectionByQuarterIdAndTeamIdNot(2L, 4L); assertEquals(12, alignmentSelections.size()); - alignmentSelections.forEach(alignmentSelection -> assertTrue( - matchAlignmentSelectionId(alignmentSelection.getAlignmentSelectionId()))); + alignmentSelections + .forEach(alignmentSelection -> assertTrue(matchAlignmentSelectionId(alignmentSelection + .getAlignmentSelectionId()))); } private boolean matchAlignmentSelectionId(AlignmentSelectionId alignmentSelectionId) { @@ -46,17 +46,18 @@ private boolean matchAlignmentSelectionId(AlignmentSelectionId alignmentSelectio } private static Stream getExpectedAlignmentSelectionIds() { - return Stream.of(AlignmentSelectionId.of(9L, 15L), // - AlignmentSelectionId.of(9L, 16L), // - AlignmentSelectionId.of(9L, 17L), // - AlignmentSelectionId.of(4L, 6L), // - AlignmentSelectionId.of(4L, 7L), // - AlignmentSelectionId.of(4L, 8L), // - AlignmentSelectionId.of(3L, 3L), // - AlignmentSelectionId.of(3L, 4L), // - AlignmentSelectionId.of(3L, 5L), // - AlignmentSelectionId.of(8L, 18L), // - AlignmentSelectionId.of(8L, 19L), // - AlignmentSelectionId.of(10L, -1L)); + return Stream + .of(AlignmentSelectionId.of(9L, 15L), // + AlignmentSelectionId.of(9L, 16L), // + AlignmentSelectionId.of(9L, 17L), // + AlignmentSelectionId.of(4L, 6L), // + AlignmentSelectionId.of(4L, 7L), // + AlignmentSelectionId.of(4L, 8L), // + AlignmentSelectionId.of(3L, 3L), // + AlignmentSelectionId.of(3L, 4L), // + AlignmentSelectionId.of(3L, 5L), // + AlignmentSelectionId.of(8L, 18L), // + AlignmentSelectionId.of(8L, 19L), // + AlignmentSelectionId.of(10L, -1L)); } } diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaIT.java index 7d1e4450ce..ca93e83964 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaIT.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static ch.puzzle.okr.test.TestHelper.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.*; -import static org.junit.jupiter.api.Assertions.assertEquals; - @SpringIntegrationTest class AuthorizationCriteriaIT { @@ -65,8 +64,8 @@ void appendObjectiveShouldReturnObjectiveWhenMemberRole() { void appendOverviewShouldReturnObjectiveWhenFirstLevelRoleAndTeamIdsEmpty() { Long quarterId = 2L; AuthorizationUser authorizationUser = defaultAuthorizationUser(); - List overviews = overviewPersistenceService.getFilteredOverview(quarterId, List.of(), "", - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(quarterId, List.of(), "", authorizationUser); assertEquals(18L, overviews.size()); } @@ -75,8 +74,8 @@ void appendOverviewShouldReturnObjectiveWhenFirstLevelRoleAndTeamIdsEmpty() { void appendOverviewShouldReturnObjectiveWhenSecondLevelRole() { Long quarterId = 2L; AuthorizationUser authorizationUser = mockAuthorizationUser(defaultUser(null)); - List overviews = overviewPersistenceService.getFilteredOverview(quarterId, List.of(5L), "", - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(quarterId, List.of(5L), "", authorizationUser); assertEquals(6L, overviews.size()); } @@ -85,8 +84,8 @@ void appendOverviewShouldReturnObjectiveWhenSecondLevelRole() { void appendOverviewShouldReturnObjectiveWhenMemberRole() { Long quarterId = 2L; AuthorizationUser authorizationUser = mockAuthorizationUser(defaultUser(null)); - List overviews = overviewPersistenceService.getFilteredOverview(quarterId, List.of(5L), "", - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(quarterId, List.of(5L), "", authorizationUser); assertEquals(6L, overviews.size()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaParametersTest.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaParametersTest.java index 7cff83afd8..0923b20a22 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaParametersTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaParametersTest.java @@ -1,8 +1,14 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static ch.puzzle.okr.test.TestHelper.mockAuthorizationUser; +import static org.junit.jupiter.api.Assertions.assertEquals; + import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.User; import jakarta.persistence.*; +import java.util.*; +import java.util.stream.Stream; import org.apache.commons.lang3.NotImplementedException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,13 +16,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.*; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static ch.puzzle.okr.test.TestHelper.mockAuthorizationUser; -import static org.junit.jupiter.api.Assertions.assertEquals; - public class AuthorizationCriteriaParametersTest { @DisplayName("setParameters() should be successful with default authorization user") @@ -43,7 +42,8 @@ void setParametersShouldBeSuccessfulWithDefaultAuthorizationUser() { @Test void setParametersShouldBeSuccessfulWhenUserIsOkrChampion() { // arrange - var user = User.Builder.builder() // + var user = User.Builder + .builder() // .withId(23L) // .withFirstname("Hanna") // .withLastname("muster") // @@ -87,11 +87,12 @@ void setParametersShouldBeSuccessfulWhenTeamIdsOrObjectiveQueryAreEmpty(List provideListAndString() { - return Stream.of( // - Arguments.of(List.of(), null), // - Arguments.of(List.of(), ""), // - Arguments.of(null, null), // - Arguments.of(null, "")); + return Stream + .of( // + Arguments.of(List.of(), null), // + Arguments.of(List.of(), ""), // + Arguments.of(null, null), // + Arguments.of(null, "")); } @DisplayName("setParameters() should be successful when team ids and objective query are not empty") @@ -118,8 +119,10 @@ void setParametersShouldBeSuccessfulWhenTeamIdsAndObjectiveQueryAreNotEmpty() { assertEquals(expected, typedQueryMock.getLog()); } - // TypedQuery implementation for testing. The setParameterX() methods calls are logged in an internal StringBuilder - // which is return by getLog(). This log can be used for checking the internal state of the TypedQuery. All other + // TypedQuery implementation for testing. The setParameterX() methods calls are + // logged in an internal StringBuilder + // which is return by getLog(). This log can be used for checking the internal + // state of the TypedQuery. All other // methods are not implemented. private static class TypedQueryMock implements TypedQuery { @@ -131,17 +134,24 @@ public String getLog() { @Override public TypedQuery setParameter(Parameter parameter, T t) { - log.append(parameter.getName()).append(", ") // - .append(t.getClass().getSimpleName()).append("=").append(t) // + log + .append(parameter.getName()) + .append(", ") // + .append(t.getClass().getSimpleName()) + .append("=") + .append(t) // .append("\n"); return null; } @Override public TypedQuery setParameter(Parameter parameter, Calendar calendar, - TemporalType temporalType) { - log.append(parameter.getName()).append(", ") // - .append(calendar.getTime()).append(", ") // + TemporalType temporalType) { + log + .append(parameter.getName()) + .append(", ") // + .append(calendar.getTime()) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; @@ -149,8 +159,11 @@ public TypedQuery setParameter(Parameter parameter, Calenda @Override public TypedQuery setParameter(Parameter parameter, Date date, TemporalType temporalType) { - log.append(parameter.getName()).append(", ") // - .append(date).append(", ") // + log + .append(parameter.getName()) + .append(", ") // + .append(date) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; @@ -158,16 +171,23 @@ public TypedQuery setParameter(Parameter parameter, Date date, @Override public TypedQuery setParameter(String s, Object o) { - log.append(s).append(", ") // - .append(o.getClass().getSimpleName()).append("=").append(o) // + log + .append(s) + .append(", ") // + .append(o.getClass().getSimpleName()) + .append("=") + .append(o) // .append("\n"); return null; } @Override public TypedQuery setParameter(String s, Calendar calendar, TemporalType temporalType) { - log.append(s).append(", ") // - .append(calendar.getTime()).append(", ") // + log + .append(s) + .append(", ") // + .append(calendar.getTime()) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; @@ -175,8 +195,11 @@ public TypedQuery setParameter(String s, Calendar calendar, TemporalT @Override public TypedQuery setParameter(String s, Date date, TemporalType temporalType) { - log.append(s).append(", ") // - .append(date).append(", ") // + log + .append(s) + .append(", ") // + .append(date) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; @@ -184,16 +207,23 @@ public TypedQuery setParameter(String s, Date date, TemporalType temp @Override public TypedQuery setParameter(int i, Object o) { - log.append(i).append(", ") // - .append(o.getClass().getSimpleName()).append("=").append(o) // + log + .append(i) + .append(", ") // + .append(o.getClass().getSimpleName()) + .append("=") + .append(o) // .append("\n"); return null; } @Override public TypedQuery setParameter(int i, Calendar calendar, TemporalType temporalType) { - log.append(i).append(", ") // - .append(calendar.getTime()).append(", ") // + log + .append(i) + .append(", ") // + .append(calendar.getTime()) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; @@ -201,8 +231,11 @@ public TypedQuery setParameter(int i, Calendar calendar, TemporalType @Override public TypedQuery setParameter(int i, Date date, TemporalType temporalType) { - log.append(i).append(", ") // - .append(date).append(", ") // + log + .append(i) + .append(", ") // + .append(date) + .append(", ") // .append(temporalType.name()) // .append("\n"); return null; diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaTest.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaTest.java index bdb382edaf..f409da5784 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/AuthorizationCriteriaTest.java @@ -1,21 +1,20 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static ch.puzzle.okr.test.TestHelper.mockAuthorizationUser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.models.User; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static ch.puzzle.okr.test.TestHelper.mockAuthorizationUser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - public class AuthorizationCriteriaTest { @DisplayName("appendObjective() should be successful with default authorization user") @@ -36,7 +35,8 @@ void appendObjectiveShouldBeSuccessfulWithDefaultAuthorizationUser() { @Test void appendObjectiveShouldBeSuccessfulWhenUserIsOkrChampion() { // arrange - var user = User.Builder.builder() // + var user = User.Builder + .builder() // .withId(23L) // .withFirstname("Hanna") // .withLastname("muster") // @@ -57,7 +57,7 @@ void appendObjectiveShouldBeSuccessfulWhenUserIsOkrChampion() { @ParameterizedTest @MethodSource("provideListAndString") void appendOverviewShouldBeSuccessfulWhenTeamIdsOrObjectiveQueryAreEmpty(List teamIds, - String objectiveQuery) { + String objectiveQuery) { // arrange var criteria = new AuthorizationCriteria(); @@ -70,11 +70,12 @@ void appendOverviewShouldBeSuccessfulWhenTeamIdsOrObjectiveQueryAreEmpty(List provideListAndString() { - return Stream.of( // - Arguments.of(List.of(), null), // - Arguments.of(List.of(), ""), // - Arguments.of(null, null), // - Arguments.of(null, "")); + return Stream + .of( // + Arguments.of(List.of(), null), // + Arguments.of(List.of(), ""), // + Arguments.of(null, null), // + Arguments.of(null, "")); } @DisplayName("appendOverview() should be successful when team ids and objective query are not empty") @@ -92,10 +93,10 @@ void appendOverviewShouldBeSuccessfulWhenTeamIdsAndObjectiveQueryAreNotEmpty() { // assert var expected = startingNewLine + singleSpace - + """ - and o.overviewId.teamId in (:teamIds) - and lower(coalesce(o.objectiveTitle, '')) like lower(concat('%',:objectiveQuery,'%')) - and ((o.objectiveState=:teamDraftState and o.overviewId.teamId IN (:userTeamIds)) or o.objectiveState IN (:publishedStates) or o.overviewId.objectiveId = -1)"""; + + """ + and o.overviewId.teamId in (:teamIds) + and lower(coalesce(o.objectiveTitle, '')) like lower(concat('%',:objectiveQuery,'%')) + and ((o.objectiveState=:teamDraftState and o.overviewId.teamId IN (:userTeamIds)) or o.objectiveState IN (:publishedStates) or o.overviewId.objectiveId = -1)"""; assertEquals(expected, current); assertFalse(current.contains(anyNonEmptyString)); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/CheckInPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/CheckInPersistenceServiceIT.java index 0837b5f996..a11b61e128 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/CheckInPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/CheckInPersistenceServiceIT.java @@ -1,24 +1,23 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.CHECK_IN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import ch.puzzle.okr.models.checkin.CheckIn; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; import ch.puzzle.okr.test.TestHelper; +import java.util.List; +import java.util.Objects; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; -import java.util.Objects; - -import static ch.puzzle.okr.Constants.CHECK_IN; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - @SpringIntegrationTest class CheckInPersistenceServiceIT { diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/CompletedPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/CompletedPersistenceServiceIT.java index 6894bfe27d..2e2d44d376 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/CompletedPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/CompletedPersistenceServiceIT.java @@ -1,25 +1,24 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Completed; import ch.puzzle.okr.models.Objective; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; - @SpringIntegrationTest class CompletedPersistenceServiceIT { @Autowired @@ -34,9 +33,13 @@ private static Completed createCompleted(Long id) { } private static Completed createCompleted(Long id, int version) { - return Completed.Builder.builder().withId(id).withVersion(version) + return Completed.Builder + .builder() + .withId(id) + .withVersion(version) .withObjective(Objective.Builder.builder().withId(OBJECTIVE_ID).withTitle(GUTE_LERNENDE).build()) - .withComment(WIR_HABEN_ES_GUT_GESCHAFFT).build(); + .withComment(WIR_HABEN_ES_GUT_GESCHAFFT) + .build(); } private static final String COMPLETED = "Completed"; @@ -91,7 +94,7 @@ void updateCompletedShouldThrowExceptionWhenAlreadyUpdated() { updateCompleted.setComment("Updated completed"); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> completedPersistenceService.save(updateCompleted)); + () -> completedPersistenceService.save(updateCompleted)); List expectedErrors = List.of(new ErrorDto("DATA_HAS_BEEN_UPDATED", List.of(COMPLETED))); @@ -107,7 +110,7 @@ void getCompletedShouldGetCompletedByObjectiveId() { assertNotNull(savedCompleted.getId()); assertEquals("War leider nicht moeglich", savedCompleted.getComment()); assertEquals("Als BBT wollen wir den Arbeitsalltag der Members von Puzzle ITC erleichtern.", - savedCompleted.getObjective().getTitle()); + savedCompleted.getObjective().getTitle()); } @Test @@ -116,7 +119,7 @@ void deleteCompletedIdShouldDeleteExistingCompletedByObjectiveId() { completedPersistenceService.deleteById(3L); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> completedPersistenceService.findById(3L)); + () -> completedPersistenceService.findById(3L)); List expectedErrors = List.of(new ErrorDto("MODEL_WITH_ID_NOT_FOUND", List.of(COMPLETED, "3"))); @@ -130,7 +133,7 @@ void deleteCompletedShouldThrowExceptionWhenCompletedNotFound() { long noExistentId = getNonExistentId(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> completedPersistenceService.findById(noExistentId)); + () -> completedPersistenceService.findById(noExistentId)); List expectedErrors = List .of(new ErrorDto("MODEL_WITH_ID_NOT_FOUND", List.of(COMPLETED, String.valueOf(noExistentId)))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java index 40296fdf4f..bd99d34753 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/KeyResultPersistenceServiceIT.java @@ -1,6 +1,9 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.http.HttpStatus.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -11,18 +14,14 @@ import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.time.LocalDateTime; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.http.HttpStatus.*; - @SpringIntegrationTest class KeyResultPersistenceServiceIT { KeyResult createdKeyResult; @@ -30,10 +29,17 @@ class KeyResultPersistenceServiceIT { private KeyResultPersistenceService keyResultPersistenceService; private static KeyResult createKeyResultMetric(Long id) { - return KeyResultMetric.Builder.builder().withBaseline(3.0).withStretchGoal(5.0).withUnit(Unit.FTE).withId(id) - .withTitle("Title").withCreatedBy(User.Builder.builder().withId(1L).build()) + return KeyResultMetric.Builder + .builder() + .withBaseline(3.0) + .withStretchGoal(5.0) + .withUnit(Unit.FTE) + .withId(id) + .withTitle("Title") + .withCreatedBy(User.Builder.builder().withId(1L).build()) .withOwner(User.Builder.builder().withId(1L).build()) - .withObjective(Objective.Builder.builder().withId(4L).build()).withCreatedOn(LocalDateTime.now()) + .withObjective(Objective.Builder.builder().withId(4L).build()) + .withCreatedOn(LocalDateTime.now()) .build(); } @@ -42,11 +48,18 @@ private static KeyResult createKeyResultOrdinal(Long id) { } private static KeyResult createKeyResultOrdinal(Long id, int version) { - return KeyResultOrdinal.Builder.builder().withCommitZone("Hamster").withTargetZone("Katze") - .withStretchZone("ZOO").withId(id).withVersion(version).withTitle("Ordinal KeyResult") + return KeyResultOrdinal.Builder + .builder() + .withCommitZone("Hamster") + .withTargetZone("Katze") + .withStretchZone("ZOO") + .withId(id) + .withVersion(version) + .withTitle("Ordinal KeyResult") .withCreatedBy(User.Builder.builder().withId(1L).build()) .withOwner(User.Builder.builder().withId(1L).build()) - .withObjective(Objective.Builder.builder().withId(4L).build()).withCreatedOn(LocalDateTime.now()) + .withObjective(Objective.Builder.builder().withId(4L).build()) + .withCreatedOn(LocalDateTime.now()) .build(); } @@ -100,7 +113,7 @@ void getKeyResultByIdShouldReturnKeyResultProperly() { @Test void getKeyResultByIdShouldThrowExceptionWhenKeyResultNotFound() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(321L)); + () -> keyResultPersistenceService.findById(321L)); List expectedErrors = List.of(new ErrorDto(MODEL_NOT_FOUND, List.of(KEYRESULT, "321"))); @@ -112,7 +125,7 @@ void getKeyResultByIdShouldThrowExceptionWhenKeyResultNotFound() { @Test void getKeyResultByIdShouldThrowExceptionWhenKeyResultIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(null)); + () -> keyResultPersistenceService.findById(null)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", KEYRESULT))); @@ -128,8 +141,8 @@ void recreateEntityShouldUpdateKeyResultNoTypeChange() { createdKeyResult.setTitle(KEY_RESULT_UPDATED); Long keyResultId = createdKeyResult.getId(); - KeyResult recreatedKeyResult = keyResultPersistenceService.recreateEntity(createdKeyResult.getId(), - createdKeyResult); + KeyResult recreatedKeyResult = keyResultPersistenceService + .recreateEntity(createdKeyResult.getId(), createdKeyResult); assertNotNull(createdKeyResult.getId()); assertEquals(KEY_RESULT_UPDATED, recreatedKeyResult.getTitle()); @@ -138,7 +151,7 @@ void recreateEntityShouldUpdateKeyResultNoTypeChange() { // Should delete the old KeyResult OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(keyResultId)); + () -> keyResultPersistenceService.findById(keyResultId)); List expectedErrors = List.of(ErrorDto.of(MODEL_NOT_FOUND, List.of(KEYRESULT, keyResultId))); @@ -155,14 +168,21 @@ void recreateEntityShouldUpdateKeyResultWithTypeChange() { KeyResult keyResult = createKeyResultMetric(null); createdKeyResult = keyResultPersistenceService.save(keyResult); - KeyResult keyResultOrdinal = KeyResultOrdinal.Builder.builder().withCommitZone("Hund") - .withTargetZone("Hund + Katze").withStretchZone("Zoo").withId(createdKeyResult.getId()) - .withTitle(KEY_RESULT_UPDATED).withObjective(createdKeyResult.getObjective()) - .withOwner(createdKeyResult.getOwner()).withCreatedBy(createdKeyResult.getCreatedBy()) - .withCreatedOn(createdKeyResult.getCreatedOn()).build(); + KeyResult keyResultOrdinal = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Hund") + .withTargetZone("Hund + Katze") + .withStretchZone("Zoo") + .withId(createdKeyResult.getId()) + .withTitle(KEY_RESULT_UPDATED) + .withObjective(createdKeyResult.getObjective()) + .withOwner(createdKeyResult.getOwner()) + .withCreatedBy(createdKeyResult.getCreatedBy()) + .withCreatedOn(createdKeyResult.getCreatedOn()) + .build(); - KeyResult recreatedKeyResult = keyResultPersistenceService.recreateEntity(keyResultOrdinal.getId(), - keyResultOrdinal); + KeyResult recreatedKeyResult = keyResultPersistenceService + .recreateEntity(keyResultOrdinal.getId(), keyResultOrdinal); assertNotNull(createdKeyResult.getId()); assertEquals(createdKeyResult.getObjective().getId(), recreatedKeyResult.getObjective().getId()); @@ -172,7 +192,7 @@ void recreateEntityShouldUpdateKeyResultWithTypeChange() { Long keyResultId = createdKeyResult.getId(); // Should delete the old KeyResult OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(keyResultId)); + () -> keyResultPersistenceService.findById(keyResultId)); List expectedErrors = List.of(ErrorDto.of(MODEL_NOT_FOUND, List.of(KEYRESULT, keyResultId))); @@ -212,7 +232,8 @@ void updateEntityShouldThrowExceptionWhenAlreadyUpdated() { updateKeyResult.setDescription(THIS_IS_DESCRIPTION); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.updateEntity(updateKeyResult)); + () -> keyResultPersistenceService + .updateEntity(updateKeyResult)); List expectedErrors = List.of(new ErrorDto("DATA_HAS_BEEN_UPDATED", List.of(KEYRESULT))); assertEquals(UNPROCESSABLE_ENTITY, exception.getStatusCode()); @@ -235,7 +256,7 @@ void deleteKeyResultByIdShouldDeleteExistingKeyResult() { Long keyResultId = createdKeyResult.getId(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(keyResultId)); + () -> keyResultPersistenceService.findById(keyResultId)); List expectedErrors = List.of(ErrorDto.of(MODEL_NOT_FOUND, List.of(KEYRESULT, keyResultId))); @@ -249,7 +270,7 @@ void deleteKeyResultShouldThrowExceptionWhenKeyResultNotFound() { long nonExistentId = getNonExistentId(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> keyResultPersistenceService.findById(nonExistentId)); + () -> keyResultPersistenceService.findById(nonExistentId)); List expectedErrors = List.of(ErrorDto.of(MODEL_NOT_FOUND, List.of(KEYRESULT, nonExistentId))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceServiceIT.java index 9708e9d779..b2f83eb360 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/ObjectivePersistenceServiceIT.java @@ -1,5 +1,13 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.exception.OkrResponseStatusException.of; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -9,6 +17,8 @@ import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; import ch.puzzle.okr.test.TestHelper; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -19,17 +29,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.exception.OkrResponseStatusException.of; -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - // tests are using data from V100_0_0__TestData.sql @SpringIntegrationTest class ObjectivePersistenceServiceIT { @@ -79,8 +78,8 @@ void tearDown() { @Test void findObjectiveByIdShouldReturnObjectiveProperly() { // act - var objective = objectivePersistenceService.findObjectiveById(ID_OF_OBJECTIVE_3, authorizationUser, - NO_RESULT_EXCEPTION); + var objective = objectivePersistenceService + .findObjectiveById(ID_OF_OBJECTIVE_3, authorizationUser, NO_RESULT_EXCEPTION); // assert assertObjective(ID_OF_OBJECTIVE_3, TITLE_OF_OBJECTIVE_3, objective); @@ -90,8 +89,11 @@ void findObjectiveByIdShouldReturnObjectiveProperly() { @Test void findObjectiveByIdShouldThrowExceptionWhenObjectiveNotFound() { // act - var exception = assertThrows(OkrResponseStatusException.class, () -> objectivePersistenceService - .findObjectiveById(INVALID_OBJECTIVE_ID, authorizationUser, NO_RESULT_EXCEPTION)); + var exception = assertThrows(OkrResponseStatusException.class, + () -> objectivePersistenceService + .findObjectiveById(INVALID_OBJECTIVE_ID, + authorizationUser, + NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(REASON_UNAUTHORIZED, List.of())); @@ -103,7 +105,8 @@ void findObjectiveByIdShouldThrowExceptionWhenObjectiveNotFound() { void findObjectiveByIdShouldThrowExceptionWhenObjectiveIdIsNull() { // act var exception = assertThrows(OkrResponseStatusException.class, - () -> objectivePersistenceService.findObjectiveById(null, authorizationUser, NO_RESULT_EXCEPTION)); + () -> objectivePersistenceService + .findObjectiveById(null, authorizationUser, NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(ATTRIBUTE_NULL, List.of("ID", OBJECTIVE))); @@ -114,8 +117,8 @@ void findObjectiveByIdShouldThrowExceptionWhenObjectiveIdIsNull() { @Test void findObjectiveByKeyResultIdShouldReturnObjectiveProperly() { // act - var objective = objectivePersistenceService.findObjectiveByKeyResultId(ID_OF_KEY_RESULT_5, authorizationUser, - NO_RESULT_EXCEPTION); + var objective = objectivePersistenceService + .findObjectiveByKeyResultId(ID_OF_KEY_RESULT_5, authorizationUser, NO_RESULT_EXCEPTION); // assert assertObjective(ID_OF_OBJECTIVE_3, TITLE_OF_OBJECTIVE_3, objective); @@ -125,8 +128,11 @@ void findObjectiveByKeyResultIdShouldReturnObjectiveProperly() { @Test void findObjectiveByKeyResultIdShouldThrowExceptionWhenObjectiveNotFound() { // act - var exception = assertThrows(OkrResponseStatusException.class, () -> objectivePersistenceService - .findObjectiveByKeyResultId(INVALID_KEY_RESULT_ID, authorizationUser, NO_RESULT_EXCEPTION)); + var exception = assertThrows(OkrResponseStatusException.class, + () -> objectivePersistenceService + .findObjectiveByKeyResultId(INVALID_KEY_RESULT_ID, + authorizationUser, + NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(REASON_UNAUTHORIZED, List.of())); @@ -137,8 +143,9 @@ void findObjectiveByKeyResultIdShouldThrowExceptionWhenObjectiveNotFound() { @Test void findObjectiveByKeyResultIdShouldThrowExceptionWhenObjectiveIdIsNull() { // act - var exception = assertThrows(OkrResponseStatusException.class, () -> objectivePersistenceService - .findObjectiveByKeyResultId(null, authorizationUser, NO_RESULT_EXCEPTION)); + var exception = assertThrows(OkrResponseStatusException.class, + () -> objectivePersistenceService + .findObjectiveByKeyResultId(null, authorizationUser, NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(ATTRIBUTE_NULL, List.of("ID", OBJECTIVE))); @@ -149,8 +156,8 @@ void findObjectiveByKeyResultIdShouldThrowExceptionWhenObjectiveIdIsNull() { @Test void findObjectiveByCheckInIdShouldReturnObjectiveProperly() { // act - var objective = objectivePersistenceService.findObjectiveByCheckInId(ID_OF_CHECK_IN_7, authorizationUser, - NO_RESULT_EXCEPTION); + var objective = objectivePersistenceService + .findObjectiveByCheckInId(ID_OF_CHECK_IN_7, authorizationUser, NO_RESULT_EXCEPTION); // assert assertObjective(ID_OF_OBJECTIVE_3, TITLE_OF_OBJECTIVE_3, objective); @@ -160,8 +167,11 @@ void findObjectiveByCheckInIdShouldReturnObjectiveProperly() { @Test void findObjectiveByCheckInIdShouldThrowExceptionWhenObjectiveNotFound() { // act - var exception = assertThrows(OkrResponseStatusException.class, () -> objectivePersistenceService - .findObjectiveByCheckInId(INVALID_CHECK_IN_ID, authorizationUser, NO_RESULT_EXCEPTION)); + var exception = assertThrows(OkrResponseStatusException.class, + () -> objectivePersistenceService + .findObjectiveByCheckInId(INVALID_CHECK_IN_ID, + authorizationUser, + NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(REASON_UNAUTHORIZED, List.of())); @@ -172,8 +182,11 @@ void findObjectiveByCheckInIdShouldThrowExceptionWhenObjectiveNotFound() { @Test void findObjectiveByCheckInIdShouldThrowExceptionWhenObjectiveIdIsNull() { // act - var exception = assertThrows(OkrResponseStatusException.class, () -> objectivePersistenceService - .findObjectiveByCheckInId(null, authorizationUser, ObjectivePersistenceServiceIT.NO_RESULT_EXCEPTION)); + var exception = assertThrows(OkrResponseStatusException.class, + () -> objectivePersistenceService + .findObjectiveByCheckInId(null, + authorizationUser, + ObjectivePersistenceServiceIT.NO_RESULT_EXCEPTION)); // assert var expectedErrors = List.of(new ErrorDto(ATTRIBUTE_NULL, List.of("ID", OBJECTIVE))); @@ -216,7 +229,8 @@ void findObjectiveByTeamIdShouldReturnEmptyListWhenObjectiveIdIsNull() { @DisplayName("countByTeamAndQuarter() should return number of objectives for current quarter") @Test void countByTeamAndQuarterShouldReturnNumberOfObjectivesForCurrentQuarter() { - // arrange: there are 3 objectives for the current quarter (id 2) for team with id 6 + // arrange: there are 3 objectives for the current quarter (id 2) for team with + // id 6 var team = Team.Builder.builder().withId(ID_OF_TEAM_6).build(); var quarter = Quarter.Builder.builder().withId(CURRENT_QUARTER_ID).build(); @@ -244,19 +258,20 @@ private static Stream invalidTeamsAndQuarters() { var validQuarter = Quarter.Builder.builder().withId(CURRENT_QUARTER_ID).build(); var invalidQuarter = Quarter.Builder.builder().withId(INVALID_QUARTER_ID).build(); - return Stream.of( - // valid team + invalid quarter - arguments(validTeam, invalidQuarter), - // valid team + null quarter - arguments(validTeam, null), - // invalid team + valid quarter - arguments(invalidTeam, validQuarter), - // invalid team + null quarter - arguments(null, validQuarter), - // invalid team + invalid quarter - arguments(invalidTeam, invalidQuarter), - // null team + null quarter - arguments(null, null)); + return Stream + .of( + // valid team + invalid quarter + arguments(validTeam, invalidQuarter), + // valid team + null quarter + arguments(validTeam, null), + // invalid team + valid quarter + arguments(invalidTeam, validQuarter), + // invalid team + null quarter + arguments(null, validQuarter), + // invalid team + invalid quarter + arguments(invalidTeam, invalidQuarter), + // null team + null quarter + arguments(null, null)); } @DisplayName("getModelName() should return Objective") @@ -266,7 +281,7 @@ void getModelNameShouldReturnObjective() { } private void assertResponseStatusException(HttpStatus expectedStatus, List expectedErrors, - OkrResponseStatusException currentException) { + OkrResponseStatusException currentException) { assertEquals(expectedStatus, currentException.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(currentException.getErrors()); assertTrue(TestHelper.getAllErrorKeys(expectedErrors).contains(currentException.getReason())); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java index fb74abd66e..1eb6486749 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/OverviewPersistenceServiceIT.java @@ -1,46 +1,46 @@ package ch.puzzle.okr.service.persistence; -import ch.puzzle.okr.test.TestHelper; +import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + import ch.puzzle.okr.models.authorization.AuthorizationUser; import ch.puzzle.okr.models.overview.Overview; import ch.puzzle.okr.models.overview.OverviewId; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; - -import static ch.puzzle.okr.test.TestHelper.defaultAuthorizationUser; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; - @SpringIntegrationTest class OverviewPersistenceServiceIT { - private static final List expectedOverviewIds = List.of( // index: - OverviewId.of(4L, 5L, 9L, 15L), // 0 - OverviewId.of(4L, 5L, 10L, 14L), // 1 - OverviewId.of(4L, 6L, 12L, 12L), // 2 - OverviewId.of(4L, 6L, 13L, 11L), // 3 - OverviewId.of(4L, 6L, 14L, 10L), // 4 - OverviewId.of(5L, 3L, 3L, 9L), // 5 - OverviewId.of(5L, 3L, 4L, 8L), // 6 - OverviewId.of(5L, 3L, 5L, 7L), // 7 - OverviewId.of(5L, 4L, 6L, 5L), // 8 - OverviewId.of(5L, 4L, 7L, 4L), // 9 - OverviewId.of(5L, 4L, 8L, 2L), // 10 - OverviewId.of(6L, 8L, 18L, 20L), // 11 - OverviewId.of(6L, 8L, 19L, 19L), // 12 - OverviewId.of(6L, 9L, 15L, 18L), // 13 - OverviewId.of(6L, 9L, 16L, 17L), // 14 - OverviewId.of(6L, 9L, 17L, 16L), // 15 - OverviewId.of(6L, 10L, -1L, -1L), // 16 - OverviewId.of(8L, -1L, -1L, -1L), // 17 - OverviewId.of(5L, -1L, -1L, -1L), // 18 - OverviewId.of(6L, -1L, -1L, -1L), // 19 - OverviewId.of(4L, -1L, -1L, -1L)); // 20 + private static final List expectedOverviewIds = List + .of( // index: + OverviewId.of(4L, 5L, 9L, 15L), // 0 + OverviewId.of(4L, 5L, 10L, 14L), // 1 + OverviewId.of(4L, 6L, 12L, 12L), // 2 + OverviewId.of(4L, 6L, 13L, 11L), // 3 + OverviewId.of(4L, 6L, 14L, 10L), // 4 + OverviewId.of(5L, 3L, 3L, 9L), // 5 + OverviewId.of(5L, 3L, 4L, 8L), // 6 + OverviewId.of(5L, 3L, 5L, 7L), // 7 + OverviewId.of(5L, 4L, 6L, 5L), // 8 + OverviewId.of(5L, 4L, 7L, 4L), // 9 + OverviewId.of(5L, 4L, 8L, 2L), // 10 + OverviewId.of(6L, 8L, 18L, 20L), // 11 + OverviewId.of(6L, 8L, 19L, 19L), // 12 + OverviewId.of(6L, 9L, 15L, 18L), // 13 + OverviewId.of(6L, 9L, 16L, 17L), // 14 + OverviewId.of(6L, 9L, 17L, 16L), // 15 + OverviewId.of(6L, 10L, -1L, -1L), // 16 + OverviewId.of(8L, -1L, -1L, -1L), // 17 + OverviewId.of(5L, -1L, -1L, -1L), // 18 + OverviewId.of(6L, -1L, -1L, -1L), // 19 + OverviewId.of(4L, -1L, -1L, -1L)); // 20 private final AuthorizationUser authorizationUser = defaultAuthorizationUser(); @Autowired @@ -58,8 +58,8 @@ void tearDown() { @Test void getFilteredOverviewShouldReturnOverviewsWhenTeamIdsSet() { - List overviews = overviewPersistenceService.getFilteredOverview(2L, List.of(5L, 6L, 8L), "", - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(2L, List.of(5L, 6L, 8L), "", authorizationUser); assertThat(expectedOverviewIds.subList(5, 18)).hasSameElementsAs(getOverviewIds(overviews)); } @@ -73,24 +73,24 @@ void getFilteredOverviewShouldReturnOverviewsWhenTeamIdsEmpty() { @Test void getFilteredOverviewShouldReturnOverviewsWhenObjectiveQuery() { - List overviews = overviewPersistenceService.getFilteredOverview(2L, List.of(5L, 6L, 8L), - "kundenzufriedenheit", authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(2L, List.of(5L, 6L, 8L), "kundenzufriedenheit", authorizationUser); assertThat(expectedOverviewIds.subList(5, 8)).hasSameElementsAs(getOverviewIds(overviews)); } @Test void getFilteredOverviewShouldReturnOverviewsWhenQuarterWithoutObjectives() { - List overviews = overviewPersistenceService.getFilteredOverview(3L, List.of(5L, 6L, 8L), null, - authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(3L, List.of(5L, 6L, 8L), null, authorizationUser); assertThat(expectedOverviewIds.subList(17, 20)).hasSameElementsAs(getOverviewIds(overviews)); } @Test void getFilteredOverviewShouldReturnOverviewsWhenQuarterWithoutObjectivesAndObjectiveQuery() { - List overviews = overviewPersistenceService.getFilteredOverview(3L, List.of(5L, 6L, 8L), - "kundenzufriedenheit", authorizationUser); + List overviews = overviewPersistenceService + .getFilteredOverview(3L, List.of(5L, 6L, 8L), "kundenzufriedenheit", authorizationUser); assertTrue(overviews.isEmpty()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/PersistenceBaseTestIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/PersistenceBaseTestIT.java index ad42955688..a6e3a8a132 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/PersistenceBaseTestIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/PersistenceBaseTestIT.java @@ -1,10 +1,19 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.test.TestHelper.getAllErrorKeys; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.models.User; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.repository.UserRepository; import ch.puzzle.okr.test.SpringIntegrationTest; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -13,20 +22,9 @@ import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.web.server.ResponseStatusException; -import java.util.List; -import java.util.stream.Collectors; - -import static ch.puzzle.okr.test.TestHelper.getAllErrorKeys; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.http.HttpStatus.*; - /** - * Testing the functionality of the abstract PersistenceBase and use UserRepository as example of a CrudRepository - * implementation. + * Testing the functionality of the abstract PersistenceBase and use + * UserRepository as example of a CrudRepository implementation. *

* Tests depending on data from V100_0_0__TestData.sql */ @@ -69,7 +67,7 @@ void findByIdShouldReturnSingleEntityIfEntityWithIdExists() { @Test void findByIdShouldThrowExceptionIfEntityWithIdDoesNotExist() { var exception = assertThrows(ResponseStatusException.class, - () -> persistenceBase.findById(NON_EXISTING_USER_ID)); + () -> persistenceBase.findById(NON_EXISTING_USER_ID)); assertEquals(NOT_FOUND, exception.getStatusCode()); assertErrorKey("MODEL_WITH_ID_NOT_FOUND", exception); @@ -162,7 +160,7 @@ void deleteByIdShouldDeleteEntity() throws ResponseStatusException { } private static void assertUser(String expectedFirstName, String expectedLastName, String expectedEmail, - User currentUser) { + User currentUser) { assertEquals(expectedFirstName, currentUser.getFirstname()); assertEquals(expectedLastName, currentUser.getLastname()); assertEquals(expectedEmail, currentUser.getEmail()); @@ -180,7 +178,11 @@ private void assertEntityNotFound(long entityId) { } private static User createUserWithUniqueName(String name) { - return User.Builder.builder().withFirstname(name).withLastname("Muster").withEmail("hans.muster@puzzle.ch") + return User.Builder + .builder() + .withFirstname(name) + .withLastname("Muster") + .withEmail("hans.muster@puzzle.ch") .build(); } } \ No newline at end of file diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/QuarterPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/QuarterPersistenceServiceIT.java index 1eee877cc1..4dd6d02829 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/QuarterPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/QuarterPersistenceServiceIT.java @@ -1,24 +1,23 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.QUARTER; +import static ch.puzzle.okr.test.TestConstants.GJ_FOR_TESTS_QUARTER_ID; +import static ch.puzzle.okr.test.TestConstants.GJ_FOR_TEST_QUARTER_LABEL; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; import ch.puzzle.okr.test.TestHelper; import ch.puzzle.okr.util.quarter.check.QuarterRangeChecker; +import java.time.LocalDate; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.time.LocalDate; -import java.util.List; - -import static ch.puzzle.okr.Constants.QUARTER; -import static ch.puzzle.okr.test.TestConstants.GJ_FOR_TESTS_QUARTER_ID; -import static ch.puzzle.okr.test.TestConstants.GJ_FOR_TEST_QUARTER_LABEL; -import static org.junit.jupiter.api.Assertions.*; - @SpringIntegrationTest class QuarterPersistenceServiceIT { @@ -46,14 +45,18 @@ void getMostCurrentQuartersShouldReturnCurrentQuarterAndFutureQuarterAndGJForTes } private void assertGJForTestsQuarterIsFoundOnce(List quarters) { - long foundGJForTestsQuartersCount = quarters.stream() - .filter(quarter -> quarter.getLabel().equals(GJ_FOR_TEST_QUARTER_LABEL)).count(); + long foundGJForTestsQuartersCount = quarters + .stream() + .filter(quarter -> quarter.getLabel().equals(GJ_FOR_TEST_QUARTER_LABEL)) + .count(); assertEquals(1, foundGJForTestsQuartersCount); } private void assertCurrentQuarterIsFoundOnce(List quarters) { - long foundCurrentQuartersCount = quarters.stream() - .filter(quarter -> QuarterRangeChecker.nowIsInQuarter(LocalDate.now(), quarter)).count(); + long foundCurrentQuartersCount = quarters + .stream() + .filter(quarter -> QuarterRangeChecker.nowIsInQuarter(LocalDate.now(), quarter)) + .count(); assertEquals(1, foundCurrentQuartersCount); } @@ -62,10 +65,10 @@ void shouldReturnCurrentQuarter() { Quarter quarter = quarterPersistenceService.getCurrentQuarter(); assertTrue(LocalDate.now().isEqual(quarter.getStartDate()) || // - LocalDate.now().isAfter(quarter.getStartDate())); + LocalDate.now().isAfter(quarter.getStartDate())); assertTrue(LocalDate.now().isEqual(quarter.getEndDate()) || // - LocalDate.now().isBefore(quarter.getEndDate())); + LocalDate.now().isBefore(quarter.getEndDate())); assertNotNull(quarter.getId()); assertNotNull(quarter.getLabel()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/TeamPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/TeamPersistenceServiceIT.java index f37812cb21..74f2e0f50f 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/TeamPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/TeamPersistenceServiceIT.java @@ -1,19 +1,18 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.TEAM; +import static org.junit.jupiter.api.Assertions.assertEquals; + import ch.puzzle.okr.models.Team; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; - -import static ch.puzzle.okr.Constants.TEAM; -import static org.junit.jupiter.api.Assertions.assertEquals; - @SpringIntegrationTest class TeamPersistenceServiceIT { diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/UserPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/UserPersistenceServiceIT.java index aab5435654..8fe2ac1b85 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/UserPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/UserPersistenceServiceIT.java @@ -1,9 +1,15 @@ package ch.puzzle.okr.service.persistence; +import static ch.puzzle.okr.Constants.USER; +import static ch.puzzle.okr.util.CollectionUtils.iterableToList; +import static org.junit.jupiter.api.Assertions.*; + import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; +import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -12,13 +18,6 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.http.HttpStatus; -import java.util.List; -import java.util.Optional; - -import static ch.puzzle.okr.Constants.USER; -import static ch.puzzle.okr.util.CollectionUtils.iterableToList; -import static org.junit.jupiter.api.Assertions.*; - @SpringIntegrationTest class UserPersistenceServiceIT { @@ -45,11 +44,13 @@ void tearDown() { @Test void saveShouldSaveUserWithEmptyUserTeamList() { // arrange - var newUser = User.Builder.builder() // + var newUser = User.Builder + .builder() // .withFirstname("Hans") // .withLastname("Muster") // .withEmail("muster@puzzle.ch") // - .withUserTeamList(List.of()).build(); + .withUserTeamList(List.of()) + .build(); // act createdUser = userPersistenceService.save(newUser); @@ -63,11 +64,13 @@ void saveShouldSaveUserWithEmptyUserTeamList() { @Test void saveShouldSaveUserWithNullUserTeamList() { // arrange - var newUser = User.Builder.builder() // + var newUser = User.Builder + .builder() // .withFirstname("Hans") // .withLastname("Muster") // .withEmail("muster@puzzle.ch") // - .withUserTeamList(null).build(); + .withUserTeamList(null) + .build(); // act createdUser = userPersistenceService.save(newUser); @@ -81,7 +84,8 @@ void saveShouldSaveUserWithNullUserTeamList() { @Test void saveAllShouldSaveAllUsersInTheInputList() { // arrange - var newUser = User.Builder.builder() // + var newUser = User.Builder + .builder() // .withFirstname("Hans") // .withLastname("Muster") // .withEmail("muster@puzzle.ch") // @@ -115,7 +119,8 @@ void getOrCreateUserShouldReturnSingleUserWhenUserFound() { @Test void getOrCreateUserShouldReturnSavedUserWhenUserNotFound() { // arrange - var newUser = User.Builder.builder() // + var newUser = User.Builder + .builder() // .withId(null) // .withFirstname("firstname") // .withLastname("lastname") // @@ -193,13 +198,14 @@ void deleteByIdShouldDeleteUserWhenUserFound() { // assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, // - () -> userPersistenceService.findById(createdUser.getId())); + () -> userPersistenceService.findById(createdUser.getId())); assertEquals(HttpStatus.NOT_FOUND, exception.getStatusCode()); } private User createUser() { - User newUser = User.Builder.builder() // + User newUser = User.Builder + .builder() // .withId(null) // .withFirstname("firstname") // .withLastname("lastname") // @@ -214,7 +220,7 @@ private User createUser() { @Test void deleteByIdShouldThrowExceptionWhenIdIsNull() { InvalidDataAccessApiUsageException exception = assertThrows(InvalidDataAccessApiUsageException.class, // - () -> userPersistenceService.deleteById(null)); + () -> userPersistenceService.deleteById(null)); assertEquals("The given id must not be null", exception.getMessage()); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceServiceIT.java b/backend/src/test/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceServiceIT.java index cc2dfe71b8..7b11855395 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceServiceIT.java +++ b/backend/src/test/java/ch/puzzle/okr/service/persistence/UserTeamPersistenceServiceIT.java @@ -3,14 +3,13 @@ import ch.puzzle.okr.multitenancy.TenantContext; import ch.puzzle.okr.test.SpringIntegrationTest; import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - // uses test date from V100_0_0__TestData.sql @SpringIntegrationTest public class UserTeamPersistenceServiceIT { diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/ActionValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/ActionValidationServiceTest.java index 1521f05a33..28b6351ec0 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/ActionValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/ActionValidationServiceTest.java @@ -1,11 +1,20 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Action; import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.service.persistence.ActionPersistenceService; +import java.util.List; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -20,34 +29,31 @@ import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @ExtendWith(MockitoExtension.class) class ActionValidationServiceTest { - private final KeyResult keyResult = KeyResultMetric.Builder.builder() // + private final KeyResult keyResult = KeyResultMetric.Builder + .builder() // .withId(10L) // - .withTitle("KR Title").build(); // + .withTitle("KR Title") + .build(); // - private final Action action1 = Action.Builder.builder() // + private final Action action1 = Action.Builder + .builder() // .withId(null) // .withAction("Neue Katze") // .withIsChecked(false) // .withPriority(0) // - .withKeyResult(keyResult).build(); + .withKeyResult(keyResult) + .build(); - private final Action action2 = Action.Builder.builder() // + private final Action action2 = Action.Builder + .builder() // .withId(2L) // .withAction("Neues Lama") // .withIsChecked(true) // // - .withPriority(1).withKeyResult(keyResult).build(); + .withPriority(1) + .withKeyResult(keyResult) + .build(); @Mock ActionPersistenceService actionPersistenceService; @@ -60,10 +66,12 @@ class ActionValidationServiceTest { private ActionValidationService validator; private static Stream actionValidationArguments() { - return Stream.of( - arguments(StringUtils.repeat('1', 5000), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("action", "Action", "0", "4096")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 5000), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("action", "Action", "0", "4096")))), + arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action"))))); } private record ActionPair(Action action, Action saveAction) { @@ -74,33 +82,67 @@ private static Stream actionPairArgument() { Long id = 3L; KeyResult keyResult = KeyResultMetric.Builder.builder().withId(10L).withTitle("KR Title").build(); // - return Stream.of( // - Arguments.of(new ActionPair( // - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) // - .withKeyResult(null).build(), - - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) // - .withKeyResult(null).build())), - - Arguments.of(new ActionPair( // - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) // - .withKeyResult(keyResult).build(), - - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) // - .withKeyResult(null).build())), - - Arguments.of(new ActionPair( // - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) // - .withKeyResult(null).build(), - - Action.Builder.builder() // - .withId(id).withAction("Action").withIsChecked(false).withPriority(1) - .withKeyResult(keyResult).build()))); + return Stream + .of( // + Arguments + .of(new ActionPair( // + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) // + .withKeyResult(null) + .build(), + + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) // + .withKeyResult(null) + .build())), + + Arguments + .of(new ActionPair( // + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) // + .withKeyResult(keyResult) + .build(), + + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) // + .withKeyResult(null) + .build())), + + Arguments + .of(new ActionPair( // + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) // + .withKeyResult(null) + .build(), + + Action.Builder + .builder() // + .withId(id) + .withAction("Action") + .withIsChecked(false) + .withPriority(1) + .withKeyResult(keyResult) + .build()))); } @BeforeEach @@ -120,11 +162,12 @@ void validateOnCreateShouldBeSuccessfulWhenActionIsValid() { void validateOnCreateShouldThrowExceptionWhenModelIsNull() { // arrange OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); // act + assert - List expectedErrors = List.of( // - new ErrorDto("MODEL_NULL", List.of("Action"))); + List expectedErrors = List + .of( // + new ErrorDto("MODEL_NULL", List.of("Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -132,11 +175,12 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { // arrange OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(action2)); + () -> validator.validateOnCreate(action2)); // act + assert - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -144,12 +188,18 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @MethodSource("actionValidationArguments") void validateOnCreateShouldThrowExceptionWhenActionIsInvalid(String actionText, List errors) { // arrange - Action action = Action.Builder.builder().withId(null).withAction(actionText).withIsChecked(false) - .withPriority(1).withKeyResult(keyResult).build(); + Action action = Action.Builder + .builder() + .withId(null) + .withAction(actionText) + .withIsChecked(false) + .withPriority(1) + .withKeyResult(keyResult) + .build(); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(action)); + () -> validator.validateOnCreate(action)); assertOkrResponseStatusException(exception, errors); } @@ -161,11 +211,12 @@ void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(actionInvalid)); + () -> validator.validateOnCreate(actionInvalid)); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("keyResult", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("keyResult", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -190,11 +241,12 @@ void validateOnUpdateShouldBeSuccessfulWhenActionIsValid() { void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { // arrange OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, null)); + () -> validator.validateOnUpdate(1L, null)); // act + assert - List expectedErrors = List.of( // - new ErrorDto("MODEL_NULL", List.of("Action"))); + List expectedErrors = List + .of( // + new ErrorDto("MODEL_NULL", List.of("Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -202,13 +254,14 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, action1)); + () -> validator.validateOnUpdate(null, action1)); verify(validator, times(1)).throwExceptionWhenModelIsNull(action1); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -216,14 +269,15 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, action2)); + () -> validator.validateOnUpdate(1L, action2)); verify(validator, times(1)).throwExceptionWhenModelIsNull(action2); verify(validator, times(1)).throwExceptionWhenIdIsNull(action2.getId()); verify(validator, times(1)).throwExceptionWhenIdHasChanged(1L, action2.getId()); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_CHANGED", List.of("ID", "1", "2"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_CHANGED", List.of("ID", "1", "2"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -236,7 +290,7 @@ void validateOnUpdateShouldThrowExceptionWhenEntityDoesNotExist() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(action2.getId(), action2)); + () -> validator.validateOnUpdate(action2.getId(), action2)); verify(validator, times(1)).throwExceptionWhenModelIsNull(action2); verify(validator, times(1)).throwExceptionWhenIdIsNull(action2.getId()); @@ -259,35 +313,42 @@ void validateOnUpdateShouldThrowExceptionWhenKeyResultNotSet(ActionPair actionPa // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(id, action)); + () -> validator.validateOnUpdate(id, action)); verify(validator, times(1)).throwExceptionWhenModelIsNull(action); verify(validator, times(1)).throwExceptionWhenIdIsNull(action.getId()); verify(validator, times(1)).throwExceptionWhenIdHasChanged(id, action.getId()); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("KeyResult", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("KeyResult", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @Test void validateOnUpdateShouldThrowExceptionWhenKeyResultIdHasChanged() { // arrange - Action action = Action.Builder.builder().withId(action2.getId()).withAction("Action").withIsChecked(false) + Action action = Action.Builder + .builder() + .withId(action2.getId()) + .withAction("Action") + .withIsChecked(false) .withPriority(1) - .withKeyResult(KeyResultMetric.Builder.builder().withId(11L).withTitle("KR Title").build()).build(); + .withKeyResult(KeyResultMetric.Builder.builder().withId(11L).withTitle("KR Title").build()) + .build(); when(actionPersistenceService.findById(anyLong())).thenReturn(action2); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(action.getId(), action)); + () -> validator.validateOnUpdate(action.getId(), action)); verify(validator, times(1)).throwExceptionWhenModelIsNull(action); verify(validator, times(1)).throwExceptionWhenIdIsNull(action.getId()); verify(validator, times(1)).throwExceptionWhenIdHasChanged(action.getId(), action2.getId()); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_CANNOT_CHANGE", List.of("KeyResult", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_CANNOT_CHANGE", List.of("KeyResult", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -295,13 +356,19 @@ void validateOnUpdateShouldThrowExceptionWhenKeyResultIdHasChanged() { @MethodSource("actionValidationArguments") void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String actionText, List errors) { // arrange - Action action = Action.Builder.builder().withId(3L).withAction(actionText).withIsChecked(false).withPriority(1) - .withKeyResult(keyResult).build(); + Action action = Action.Builder + .builder() + .withId(3L) + .withAction(actionText) + .withIsChecked(false) + .withPriority(1) + .withKeyResult(keyResult) + .build(); when(actionPersistenceService.findById(anyLong())).thenReturn(action); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(3L, action)); + () -> validator.validateOnUpdate(3L, action)); assertOkrResponseStatusException(exception, errors); } @@ -313,26 +380,32 @@ void validateOnUpdateShouldThrowExceptionWhenKeyResultIsMissing() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(11L, actionInvalid)); + () -> validator.validateOnUpdate(11L, actionInvalid)); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("KeyResult", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("KeyResult", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } @Test void validateOnUpdateShouldThrowExceptionWhenAttrsAreMissing() { // arrange - Action actionInvalid = Action.Builder.builder().withId(11L).withIsChecked(true).withKeyResult(keyResult) + Action actionInvalid = Action.Builder + .builder() + .withId(11L) + .withIsChecked(true) + .withKeyResult(keyResult) .build(); when(actionPersistenceService.findById(anyLong())).thenReturn(actionInvalid); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(11L, actionInvalid)); + () -> validator.validateOnUpdate(11L, actionInvalid)); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("action", "Action"))); assertOkrResponseStatusException(exception, expectedErrors); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/AlignmentValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/AlignmentValidationServiceTest.java index 3ab1fee119..2f6ae1b47d 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/AlignmentValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/AlignmentValidationServiceTest.java @@ -1,11 +1,18 @@ package ch.puzzle.okr.service.validation; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import ch.puzzle.okr.ErrorKey; import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.alignment.Alignment; import ch.puzzle.okr.models.alignment.KeyResultAlignment; import ch.puzzle.okr.service.persistence.AlignmentPersistenceService; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -15,14 +22,6 @@ import org.springframework.http.HttpStatus; import org.springframework.test.context.bean.override.mockito.MockitoBean; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class AlignmentValidationServiceTest { @MockitoBean @@ -71,11 +70,11 @@ void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { Alignment alignment = KeyResultAlignment.Builder.builder().withId(3L).build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, alignment)); + () -> validator.validateOnUpdate(1L, alignment)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals(List.of(new ErrorDto(ErrorKey.ATTRIBUTE_CHANGED.name(), List.of("ID", "1", "3"))), - exception.getErrors()); + exception.getErrors()); verify(validator, times(1)).throwExceptionWhenIdHasChanged(1L, 3L); } diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/CheckInValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/CheckInValidationServiceTest.java index b4a1801da5..1792f668c2 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/CheckInValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/CheckInValidationServiceTest.java @@ -1,5 +1,10 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.*; @@ -11,6 +16,9 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; import ch.puzzle.okr.service.persistence.CheckInPersistenceService; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,54 +31,95 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.mock.mockito.MockBean; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class CheckInValidationServiceTest { @MockBean CheckInPersistenceService checkInPersistenceService = Mockito.mock(CheckInPersistenceService.class); - private final User user = User.Builder.builder().withId(1L).withFirstname("Ruedi").withLastname("Grochde") - .withEmail("grochde@puzzle.ch").build(); + private final User user = User.Builder + .builder() + .withId(1L) + .withFirstname("Ruedi") + .withLastname("Grochde") + .withEmail("grochde@puzzle.ch") + .build(); private final Team team = Team.Builder.builder().withId(1L).withName("Team4").build(); private final Quarter quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build(); - private final Objective objective = Objective.Builder.builder().withId(1L).withTitle("Objective 1") - .withCreatedBy(user).withTeam(team).withQuarter(quarter).withDescription("This is our description") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withModifiedBy(user) - .withCreatedOn(LocalDateTime.MAX).build(); - private final KeyResult keyResultMetric = KeyResultMetric.Builder.builder().withBaseline(13D).withStretchGoal(25D) - .withUnit(Unit.NUMBER).withId(8L).withTitle("Keyresult Metric").withObjective(objective).withOwner(user) + private final Objective objective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Objective 1") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withDescription("This is our description") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withModifiedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .build(); + private final KeyResult keyResultMetric = KeyResultMetric.Builder + .builder() + .withBaseline(13D) + .withStretchGoal(25D) + .withUnit(Unit.NUMBER) + .withId(8L) + .withTitle("Keyresult Metric") + .withObjective(objective) + .withOwner(user) + .build(); + private final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Commit Zone") + .withTargetZone("Target Zone") + .withTitle("Keyresult Ordinal") + .withObjective(objective) + .withOwner(user) + .build(); + private final CheckIn checkInMetric = CheckInMetric.Builder + .builder() + .withValue(45D) + .withChangeInfo("ChangeInfo") + .withInitiatives("Initiatives") + .withConfidence(10) + .withKeyResult(keyResultMetric) + .withCreatedOn(LocalDateTime.MAX) + .withModifiedOn(LocalDateTime.MAX) + .withCreatedBy(user) .build(); - private final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder.builder().withCommitZone("Commit Zone") - .withTargetZone("Target Zone").withTitle("Keyresult Ordinal").withObjective(objective).withOwner(user) + private final CheckIn checkInOrdinal = CheckInMetric.Builder + .builder() + .withValue(27D) + .withId(1L) + .withChangeInfo("ChangeInfoMetric") + .withInitiatives("InitiativesMetric") + .withConfidence(8) + .withKeyResult(keyResultOrdinal) + .withCreatedOn(LocalDateTime.MAX) + .withModifiedOn(LocalDateTime.MAX) + .withCreatedBy(user) + .build(); + private final CheckIn fullCheckIn = CheckInOrdinal.Builder + .builder() + .withZone(Zone.STRETCH) + .withId(1L) + .withChangeInfo("ChangeInfoMetric") + .withInitiatives("InitiativesMetric") + .withConfidence(8) + .withKeyResult(keyResultMetric) + .withCreatedOn(LocalDateTime.MAX) + .withModifiedOn(LocalDateTime.MAX) + .withCreatedBy(user) .build(); - private final CheckIn checkInMetric = CheckInMetric.Builder.builder().withValue(45D).withChangeInfo("ChangeInfo") - .withInitiatives("Initiatives").withConfidence(10).withKeyResult(keyResultMetric) - .withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX).withCreatedBy(user).build(); - private final CheckIn checkInOrdinal = CheckInMetric.Builder.builder().withValue(27D).withId(1L) - .withChangeInfo("ChangeInfoMetric").withInitiatives("InitiativesMetric").withConfidence(8) - .withKeyResult(keyResultOrdinal).withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX) - .withCreatedBy(user).build(); - private final CheckIn fullCheckIn = CheckInOrdinal.Builder.builder().withZone(Zone.STRETCH).withId(1L) - .withChangeInfo("ChangeInfoMetric").withInitiatives("InitiativesMetric").withConfidence(8) - .withKeyResult(keyResultMetric).withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX) - .withCreatedBy(user).build(); @Spy @InjectMocks private CheckInValidationService validator; private static Stream confidenceValidationArguments() { - return Stream.of( - arguments(-1, List.of(new ErrorDto("ATTRIBUTE_MIN_VALUE", List.of("confidence", "CheckIn", "0")))), - arguments(11, List.of(new ErrorDto("ATTRIBUTE_MAX_VALUE", List.of("confidence", "CheckIn", "10")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn"))))); + return Stream + .of(arguments(-1, List.of(new ErrorDto("ATTRIBUTE_MIN_VALUE", List.of("confidence", "CheckIn", "0")))), + arguments(11, List.of(new ErrorDto("ATTRIBUTE_MAX_VALUE", List.of("confidence", "CheckIn", "10")))), + arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn"))))); } @BeforeEach @@ -88,7 +137,7 @@ void validateOnGetShouldBeSuccessfulWhenValidCheckInId() { void validateOnGetShouldThrowExceptionIfCheckInIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -111,7 +160,7 @@ void validateOnCreateShouldBeSuccessfulWhenCheckInIsValid() { void validateOnCreateShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("CheckIn"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -121,7 +170,7 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(fullCheckIn)); + () -> validator.validateOnCreate(fullCheckIn)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "CheckIn"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -130,10 +179,11 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @ParameterizedTest @MethodSource("confidenceValidationArguments") void validateOnCreateShouldThrowExceptionWhenConfidenceIsInvalid(Integer confidence, - List expectedErrors) { + List expectedErrors) { // arrange - CheckIn checkIn = CheckInMetric.Builder.builder() // + CheckIn checkIn = CheckInMetric.Builder + .builder() // .withValue(40.9) // .withChangeInfo("ChangeInfo") // .withInitiatives("Initiatives") // @@ -146,27 +196,30 @@ void validateOnCreateShouldThrowExceptionWhenConfidenceIsInvalid(Integer confide // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(checkIn)); + () -> validator.validateOnCreate(checkIn)); assertOkrResponseStatusException(exception, expectedErrors); } @Test void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { // arrange - CheckIn checkInInvalid = CheckInMetric.Builder.builder() // + CheckIn checkInInvalid = CheckInMetric.Builder + .builder() // .withId(null) // - .withChangeInfo("ChangeInfo").build(); + .withChangeInfo("ChangeInfo") + .build(); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(checkInInvalid)); - - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("keyResult", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("valueMetric", "CheckIn"))); + () -> validator.validateOnCreate(checkInInvalid)); + + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("keyResult", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("valueMetric", "CheckIn"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -186,7 +239,7 @@ void validateOnUpdateShouldBeSuccessfulWhenCheckInIsValid() { void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, null)); + () -> validator.validateOnUpdate(1L, null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("CheckIn"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -196,7 +249,7 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, checkInOrdinal)); + () -> validator.validateOnUpdate(null, checkInOrdinal)); verify(validator, times(1)).throwExceptionWhenModelIsNull(checkInOrdinal); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -209,7 +262,7 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdIsHasChanged() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(2L, checkInOrdinal)); + () -> validator.validateOnUpdate(2L, checkInOrdinal)); verify(validator, times(1)).throwExceptionWhenModelIsNull(checkInOrdinal); verify(validator, times(1)).throwExceptionWhenIdIsNull(2L); @@ -222,19 +275,27 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsHasChanged() { @ParameterizedTest @MethodSource("confidenceValidationArguments") void validateOnUpdateShouldThrowExceptionWhenConfidenceIsInvalid(Integer confidence, - List expectedErrors) { + List expectedErrors) { // arrange Long id = 2L; - CheckIn checkIn = CheckInMetric.Builder.builder().withValue(40.9).withId(id).withChangeInfo("ChangeInfo") - .withInitiatives("Initiatives").withConfidence(confidence).withCreatedBy(user) - .withKeyResult(keyResultMetric).withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX) + CheckIn checkIn = CheckInMetric.Builder + .builder() + .withValue(40.9) + .withId(id) + .withChangeInfo("ChangeInfo") + .withInitiatives("Initiatives") + .withConfidence(confidence) + .withCreatedBy(user) + .withKeyResult(keyResultMetric) + .withCreatedOn(LocalDateTime.MAX) + .withModifiedOn(LocalDateTime.MAX) .build(); when(checkInPersistenceService.findById(id)).thenReturn(checkIn); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(id, checkIn)); + () -> validator.validateOnUpdate(id, checkIn)); assertOkrResponseStatusException(exception, expectedErrors); } @@ -242,17 +303,31 @@ void validateOnUpdateShouldThrowExceptionWhenConfidenceIsInvalid(Integer confide void validateOnUpdateShouldThrowExceptionWhenCheckInsOfKeyResultIsEmpty() { // arrange Long id = 2L; - CheckIn checkIn = CheckInMetric.Builder.builder().withValue(40.9).withId(id).withChangeInfo("ChangeInfo") - .withInitiatives("Initiatives").withConfidence(2).withCreatedBy(user).withKeyResult(keyResultMetric) - .withCreatedOn(LocalDateTime.MAX).withModifiedOn(LocalDateTime.MAX).build(); - CheckIn savedCheckIn = CheckInMetric.Builder.builder().withId(id).withChangeInfo("") - .withInitiatives("Initiatives").withCreatedBy(user) - .withKeyResult(KeyResultMetric.Builder.builder().withId(13L).build()).build(); + CheckIn checkIn = CheckInMetric.Builder + .builder() + .withValue(40.9) + .withId(id) + .withChangeInfo("ChangeInfo") + .withInitiatives("Initiatives") + .withConfidence(2) + .withCreatedBy(user) + .withKeyResult(keyResultMetric) + .withCreatedOn(LocalDateTime.MAX) + .withModifiedOn(LocalDateTime.MAX) + .build(); + CheckIn savedCheckIn = CheckInMetric.Builder + .builder() + .withId(id) + .withChangeInfo("") + .withInitiatives("Initiatives") + .withCreatedBy(user) + .withKeyResult(KeyResultMetric.Builder.builder().withId(13L).build()) + .build(); when(checkInPersistenceService.findById(id)).thenReturn(savedCheckIn); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(id, checkIn)); + () -> validator.validateOnUpdate(id, checkIn)); verify(validator, times(1)).throwExceptionWhenModelIsNull(checkIn); verify(validator, times(1)).throwExceptionWhenIdIsNull(checkIn.getId()); @@ -267,7 +342,8 @@ void validateOnUpdateShouldThrowExceptionWhenCheckInsOfKeyResultIsEmpty() { void validateOnUpdateShouldThrowExceptionWhenAttrsAreMissing() { // arrange Long id = 11L; - CheckIn checkInInvalid = CheckInMetric.Builder.builder() // + CheckIn checkInInvalid = CheckInMetric.Builder + .builder() // .withId(id) // .withChangeInfo("ChangeInfo") // .withKeyResult(KeyResultMetric.Builder.builder().withId(13L).build()) // @@ -276,13 +352,14 @@ void validateOnUpdateShouldThrowExceptionWhenAttrsAreMissing() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(id, checkInInvalid)); + () -> validator.validateOnUpdate(id, checkInInvalid)); - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "CheckIn")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("valueMetric", "CheckIn"))); + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("confidence", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "CheckIn")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("valueMetric", "CheckIn"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -297,7 +374,7 @@ void validateOnDeleteShouldBeSuccessfulWhenValidKeyResultId() { void validateOnDeleteShouldThrowExceptionIfKeyResultIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnDelete(null)); + () -> validator.validateOnDelete(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/CompletedValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/CompletedValidationServiceTest.java index 3fbe650e14..38849e0379 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/CompletedValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/CompletedValidationServiceTest.java @@ -1,9 +1,17 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.*; import ch.puzzle.okr.service.persistence.CompletedPersistenceService; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -20,15 +28,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class CompletedValidationServiceTest { @MockBean @@ -43,24 +42,45 @@ class CompletedValidationServiceTest { @BeforeEach void setUp() { - this.user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + this.user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); this.team = Team.Builder.builder().withId(1L).withName("Team1").build(); this.quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build(); - this.objective = Objective.Builder.builder().withId(1L).withTitle("Objective 1").withCreatedBy(user) - .withTeam(team).withQuarter(quarter).withDescription("This is our description") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withModifiedBy(user) - .withCreatedOn(LocalDateTime.MAX).build(); + this.objective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Objective 1") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withDescription("This is our description") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withModifiedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .build(); - this.validCompleted = Completed.Builder.builder().withObjective(this.objective).withComment("Valid Comment") + this.validCompleted = Completed.Builder + .builder() + .withObjective(this.objective) + .withComment("Valid Comment") .build(); when(completedPersistenceService.getCompletedByObjectiveId(1L)).thenReturn(this.validCompleted); when(completedPersistenceService.getModelName()).thenReturn("Completed"); doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, - String.format("%s with id %s not found", completedPersistenceService.getModelName(), 2L))) - .when(completedPersistenceService).getCompletedByObjectiveId(2L); + String + .format("%s with id %s not found", + completedPersistenceService.getModelName(), + 2L))) + .when(completedPersistenceService) + .getCompletedByObjectiveId(2L); } @Spy @@ -68,8 +88,11 @@ void setUp() { private CompletedValidationService validator; private static Stream nameValidationArguments() { - return Stream.of(arguments(StringUtils.repeat('1', 5000), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("comment", "Completed", "0", "4096"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 5000), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("comment", "Completed", "0", "4096"))))); } @Test @@ -84,7 +107,7 @@ void validateOnCreateShouldBeSuccessfulWhenCompletedIsValid() { void validateOnCreateShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Completed"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -93,7 +116,8 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { // arrange - Completed completed = Completed.Builder.builder() // + Completed completed = Completed.Builder + .builder() // .withId(300L) // .withObjective(this.objective) // .withComment("Not valid") // @@ -101,7 +125,7 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(completed)); + () -> validator.validateOnCreate(completed)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Completed"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -111,14 +135,15 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @MethodSource("nameValidationArguments") void validateOnCreateShouldThrowExceptionWhenCommentIsInvalid(String comment, List expectedErrors) { // arrange - Completed completed = Completed.Builder.builder() // + Completed completed = Completed.Builder + .builder() // .withObjective(this.objective) // .withComment(comment) // .build(); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(completed)); + () -> validator.validateOnCreate(completed)); assertOkrResponseStatusException(exception, expectedErrors); } @@ -126,7 +151,8 @@ void validateOnCreateShouldThrowExceptionWhenCommentIsInvalid(String comment, Li @Test void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { // arrange - Completed completedInvalid = Completed.Builder.builder() // + Completed completedInvalid = Completed.Builder + .builder() // .withId(null) // .withComment("Valid comment") // .withObjective(null) // @@ -134,7 +160,7 @@ void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(completedInvalid)); + () -> validator.validateOnCreate(completedInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("objective", "Completed"))); assertOkrResponseStatusException(exception, expectedErrors); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/KeyResultValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/KeyResultValidationServiceTest.java index 5eaa2aa827..9428f12c87 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/KeyResultValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/KeyResultValidationServiceTest.java @@ -1,5 +1,12 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.KEY_RESULT; +import static ch.puzzle.okr.Constants.OBJECTIVE; +import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.*; @@ -7,6 +14,9 @@ import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; import ch.puzzle.okr.service.persistence.KeyResultPersistenceService; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -23,40 +33,65 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; -import static ch.puzzle.okr.Constants.KEY_RESULT; -import static ch.puzzle.okr.Constants.OBJECTIVE; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class KeyResultValidationServiceTest { @MockBean KeyResultPersistenceService keyResultPersistenceService = Mockito.mock(KeyResultPersistenceService.class); - private final User user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + private final User user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); private final Quarter quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2").build(); private final Team team = Team.Builder.builder().withId(1L).withName("Team1").build(); - private final Objective objective = Objective.Builder.builder().withId(1L).withTitle("Objective 1") - .withCreatedBy(user).withTeam(team).withQuarter(quarter).withDescription("This is our description") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withModifiedBy(user) - .withCreatedOn(LocalDateTime.MAX).build(); - private final KeyResult keyResultMetric = KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(7.0) - .withUnit(Unit.NUMBER).withId(5L).withTitle("Keyresult Metric").withObjective(objective).withOwner(user) + private final Objective objective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Objective 1") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withDescription("This is our description") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withModifiedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .build(); + private final KeyResult keyResultMetric = KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(7.0) + .withUnit(Unit.NUMBER) + .withId(5L) + .withTitle("Keyresult Metric") + .withObjective(objective) + .withOwner(user) + .build(); + private final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder + .builder() + .withCommitZone("Ein Baum") + .withTargetZone("Zwei Bäume") + .withTitle("Keyresult Ordinal") + .withObjective(objective) + .withOwner(user) .build(); - private final KeyResult keyResultOrdinal = KeyResultOrdinal.Builder.builder().withCommitZone("Ein Baum") - .withTargetZone("Zwei Bäume").withTitle("Keyresult Ordinal").withObjective(objective).withOwner(user) + private final KeyResult fullKeyResult = KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(7.0) + .withUnit(Unit.FTE) + .withId(null) + .withTitle("Keyresult Metric") + .withObjective(objective) + .withOwner(user) + .withCreatedOn(LocalDateTime.MIN) + .withModifiedOn(LocalDateTime.MAX) + .withDescription("Description") + .withCreatedBy(user) .build(); - private final KeyResult fullKeyResult = KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(7.0) - .withUnit(Unit.FTE).withId(null).withTitle("Keyresult Metric").withObjective(objective).withOwner(user) - .withCreatedOn(LocalDateTime.MIN).withModifiedOn(LocalDateTime.MAX).withDescription("Description") - .withCreatedBy(user).build(); @BeforeEach void setUp() { @@ -72,20 +107,30 @@ void setUp() { private KeyResultValidationService validator; private static Stream nameValidationArguments() { - return Stream.of( - arguments(StringUtils.repeat('1', 251), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "KeyResult", "2", "250")))), - arguments(StringUtils.repeat('1', 1), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "KeyResult", "2", "250")))), - arguments("", - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "KeyResult", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), - arguments(" ", - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "KeyResult", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), - arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("title", "KeyResult")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 251), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "KeyResult", "2", "250")))), + arguments(StringUtils.repeat('1', 1), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "KeyResult", "2", "250")))), + arguments("", + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "KeyResult", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), + arguments(" ", + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "KeyResult", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), + arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult")))), + arguments(null, + List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("title", "KeyResult")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "KeyResult"))))); } @Test @@ -100,7 +145,7 @@ void validateOnGetShouldBeSuccessfulWhenValidKeyResultId() { void validateOnGetShouldThrowExceptionIfKeyResultIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -120,7 +165,7 @@ void validateOnCreateShouldBeSuccessfulWhenKeyResultIsValid() { void validateOnCreateShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("KeyResult"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -130,7 +175,7 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(keyResultMetric)); + () -> validator.validateOnCreate(keyResultMetric)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "KeyResult"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -140,7 +185,8 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @MethodSource("nameValidationArguments") void validateOnCreateShouldThrowExceptionWhenTitleIsInvalid(String title, List errors) { // arrange - KeyResult keyResult = KeyResultMetric.Builder.builder() // + KeyResult keyResult = KeyResultMetric.Builder + .builder() // .withBaseline(3.0) // .withStretchGoal(5.0) // .withUnit(Unit.EUR) // @@ -154,30 +200,32 @@ void validateOnCreateShouldThrowExceptionWhenTitleIsInvalid(String title, List validator.validateOnCreate(keyResult)); + () -> validator.validateOnCreate(keyResult)); assertOkrResponseStatusException(exception, errors); } @Test void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { // arrange - KeyResult keyResultInvalid = KeyResultMetric.Builder.builder() // + KeyResult keyResultInvalid = KeyResultMetric.Builder + .builder() // .withId(null) // .withTitle("Title") // .build(); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(keyResultInvalid)); - - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("owner", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("stretchGoal", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("objective", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("baseline", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("unit", "KeyResult"))); + () -> validator.validateOnCreate(keyResultInvalid)); + + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("owner", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("stretchGoal", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("objective", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("baseline", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("unit", "KeyResult"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -185,10 +233,20 @@ void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { void validateOnUpdateShouldBeSuccessfulWhenKeyResultIsValid() { // arrange Long id = 5L; - KeyResult keyResult = KeyResultMetric.Builder.builder().withBaseline(4.0).withStretchGoal(7.0) - .withUnit(Unit.EUR).withId(id).withTitle("Keyresult Metric").withObjective(objective).withOwner(user) - .withCreatedOn(LocalDateTime.MIN).withModifiedOn(LocalDateTime.MAX).withDescription("Description") - .withCreatedBy(user).build(); + KeyResult keyResult = KeyResultMetric.Builder + .builder() + .withBaseline(4.0) + .withStretchGoal(7.0) + .withUnit(Unit.EUR) + .withId(id) + .withTitle("Keyresult Metric") + .withObjective(objective) + .withOwner(user) + .withCreatedOn(LocalDateTime.MIN) + .withModifiedOn(LocalDateTime.MAX) + .withDescription("Description") + .withCreatedBy(user) + .build(); when(keyResultPersistenceService.findById(id)).thenReturn(keyResult); // act @@ -205,7 +263,7 @@ void validateOnUpdateShouldBeSuccessfulWhenKeyResultIsValid() { void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, null)); + () -> validator.validateOnUpdate(1L, null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("KeyResult"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -215,7 +273,7 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, keyResultOrdinal)); + () -> validator.validateOnUpdate(null, keyResultOrdinal)); verify(validator, times(1)).throwExceptionWhenModelIsNull(keyResultOrdinal); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -228,7 +286,7 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, keyResultMetric)); + () -> validator.validateOnUpdate(1L, keyResultMetric)); verify(validator, times(1)).throwExceptionWhenModelIsNull(keyResultMetric); verify(validator, times(1)).throwExceptionWhenIdIsNull(keyResultMetric.getId()); @@ -243,7 +301,8 @@ void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String title, List errors) { // arrange Long id = 3L; - KeyResult keyResult = KeyResultMetric.Builder.builder() // + KeyResult keyResult = KeyResultMetric.Builder + .builder() // .withBaseline(3.0) // .withStretchGoal(5.0) // .withUnit(Unit.FTE) // @@ -258,7 +317,7 @@ void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String title, List validator.validateOnUpdate(id, keyResult)); + () -> validator.validateOnUpdate(id, keyResult)); assertOkrResponseStatusException(exception, errors); } @@ -267,7 +326,8 @@ void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String title, List validator.validateOnUpdate(id, keyResultInvalid)); - - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("baseline", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("stretchGoal", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("unit", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "KeyResult")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("owner", "KeyResult"))); + () -> validator.validateOnUpdate(id, keyResultInvalid)); + + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("baseline", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("stretchGoal", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("unit", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "KeyResult")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("owner", "KeyResult"))); assertOkrResponseStatusException(exception, expectedErrors); } @@ -300,7 +361,7 @@ void validateOnDeleteShouldBeSuccessfulWhenValidKeyResultId() { void validateOnDeleteShouldThrowExceptionIfKeyResultIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -315,21 +376,25 @@ void validateOnUpdateShouldThrowExceptionWhenObjectiveIdOfKeyResultHasChanged() Long keyResultId = 1L; Long objectiveId = 2L; Objective objective = Objective.Builder.builder().withId(objectiveId).build(); - KeyResult keyResult = KeyResultMetric.Builder.builder() // + KeyResult keyResult = KeyResultMetric.Builder + .builder() // .withId(keyResultId) // - .withObjective(objective).build(); + .withObjective(objective) + .build(); Long savedObjectiveId = 3L; Objective savedObjective = Objective.Builder.builder().withId(savedObjectiveId).build(); - KeyResult savedKeyResultWithDifferentObjectiveId = KeyResultMetric.Builder.builder() // + KeyResult savedKeyResultWithDifferentObjectiveId = KeyResultMetric.Builder + .builder() // .withId(keyResultId) // - .withObjective(savedObjective).build(); + .withObjective(savedObjective) + .build(); when(keyResultPersistenceService.findById(keyResultId)).thenReturn(savedKeyResultWithDifferentObjectiveId); // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(keyResultId, keyResult)); + () -> validator.validateOnUpdate(keyResultId, keyResult)); List expectedErrors = List .of(new ErrorDto("ATTRIBUTE_CANNOT_CHANGE", List.of(OBJECTIVE, KEY_RESULT))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/ObjectiveValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/ObjectiveValidationServiceTest.java index cc52bad997..2fae85f0be 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/ObjectiveValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/ObjectiveValidationServiceTest.java @@ -1,10 +1,23 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; +import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.*; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.test.TestHelper; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -20,20 +33,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Stream; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; -import static ch.puzzle.okr.test.TestConstants.BACK_LOG_QUARTER_ID; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; - @ExtendWith(MockitoExtension.class) class ObjectiveValidationServiceTest { @MockBean @@ -49,46 +48,87 @@ class ObjectiveValidationServiceTest { private ObjectiveValidationService validator; private static Stream nameValidationArguments() { - return Stream.of( - arguments(StringUtils.repeat('1', 251), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")))), - arguments(StringUtils.repeat('1', 1), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")))), - - arguments("", - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), - - arguments(" ", - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), - - arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("title", "Objective"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 251), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "Objective", "2", "250")))), + arguments(StringUtils.repeat('1', 1), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "Objective", "2", "250")))), + + arguments("", + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "Objective", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), + + arguments(" ", + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("title", "Objective", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), + + arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")))), + arguments(null, + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("title", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("title", "Objective"))))); } @BeforeEach void setUp() { - this.user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + this.user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); this.team = Team.Builder.builder().withId(1L).withName("Team1").build(); - this.quarter = Quarter.Builder.builder().withId(1L).withLabel("GJ 22/23-Q2") - .withStartDate(LocalDate.of(2022, 1, 1)).withEndDate(LocalDate.of(2022, 3, 31)).build(); + this.quarter = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ 22/23-Q2") + .withStartDate(LocalDate.of(2022, 1, 1)) + .withEndDate(LocalDate.of(2022, 3, 31)) + .build(); - this.objective1 = Objective.Builder.builder().withId(1L).withTitle("Objective 1").withCreatedBy(user) - .withTeam(team).withQuarter(quarter).withDescription("This is our description") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withModifiedBy(user) - .withCreatedOn(LocalDateTime.MAX).build(); + this.objective1 = Objective.Builder + .builder() + .withId(1L) + .withTitle("Objective 1") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withDescription("This is our description") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withModifiedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .build(); - this.objectiveMinimal = Objective.Builder.builder().withId(null).withTitle("Objective 2").withCreatedBy(user) - .withTeam(team).withQuarter(quarter).withState(State.DRAFT).withCreatedOn(LocalDateTime.MAX).build(); + this.objectiveMinimal = Objective.Builder + .builder() + .withId(null) + .withTitle("Objective 2") + .withCreatedBy(user) + .withTeam(team) + .withQuarter(quarter) + .withState(State.DRAFT) + .withCreatedOn(LocalDateTime.MAX) + .build(); when(objectivePersistenceService.findById(1L)).thenReturn(objective1); when(objectivePersistenceService.getModelName()).thenReturn("Objective"); doThrow(new OkrResponseStatusException(HttpStatus.NOT_FOUND, - String.format("%s with id %s not found", objectivePersistenceService.getModelName(), 2L))) - .when(objectivePersistenceService).findById(2L); + String + .format("%s with id %s not found", + objectivePersistenceService.getModelName(), + 2L))) + .when(objectivePersistenceService) + .findById(2L); } @Test @@ -102,7 +142,7 @@ void validateOnGetShouldBeSuccessfulWhenValidObjectiveId() { @Test void validateOnGetShouldThrowExceptionIfObjectiveIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Objective"))); @@ -123,7 +163,7 @@ void validateOnCreateShouldBeSuccessfulWhenTeamIsValid() { @Test void validateOnCreateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Objective"))); @@ -135,7 +175,7 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(objective1)); + () -> validator.validateOnCreate(objective1)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Objective"))); @@ -147,12 +187,21 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @ParameterizedTest @MethodSource("nameValidationArguments") void validateOnCreateShouldThrowExceptionWhenTitleIsInvalid(String title, List expectedErrors) { - Objective objective = Objective.Builder.builder().withId(null).withTitle(title).withCreatedBy(this.user) - .withTeam(this.team).withQuarter(this.quarter).withDescription("This is our description 2") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withCreatedOn(LocalDateTime.MAX).build(); + Objective objective = Objective.Builder + .builder() + .withId(null) + .withTitle(title) + .withCreatedBy(this.user) + .withTeam(this.team) + .withQuarter(this.quarter) + .withDescription("This is our description 2") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withCreatedOn(LocalDateTime.MAX) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(objective)); + () -> validator.validateOnCreate(objective)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -161,15 +210,20 @@ void validateOnCreateShouldThrowExceptionWhenTitleIsInvalid(String title, List validator.validateOnCreate(objectiveInvalid)); + () -> validator.validateOnCreate(objectiveInvalid)); - List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective"))); + List expectedErrors = List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -178,14 +232,25 @@ void validateOnCreateShouldThrowExceptionWhenAttrsAreMissing() { @Test void validateOnCreateShouldThrowExceptionWhenAttrModifiedByIsSet() { - Objective objectiveInvalid = Objective.Builder.builder().withId(null) - .withTitle("ModifiedBy is not null on create").withCreatedBy(user).withCreatedOn(LocalDateTime.MAX) - .withState(State.DRAFT).withTeam(team).withQuarter(quarter).withModifiedBy(user).build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(null) + .withTitle("ModifiedBy is not null on create") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(quarter) + .withModifiedBy(user) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(objectiveInvalid)); - List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_SET_FORBIDDEN", List.of("ModifiedBy", - "User{id=1, version=0, firstname='Bob', lastname='Kaufmann', email='kaufmann@puzzle.ch', isOkrChampion='false'}"))); + () -> validator.validateOnCreate(objectiveInvalid)); + List expectedErrors = List + .of(new ErrorDto("ATTRIBUTE_SET_FORBIDDEN", + List + .of("ModifiedBy", + "User{id=1, version=0, firstname='Bob', lastname='Kaufmann', email='kaufmann@puzzle.ch', isOkrChampion='false'}"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -194,14 +259,25 @@ void validateOnCreateShouldThrowExceptionWhenAttrModifiedByIsSet() { @Test void validateOnCreateShouldThrowExceptionWhenStartDateIsNull() { - Quarter invalidQuarter = Quarter.Builder.builder().withId(1L).withLabel("GJ-22/23-Q3") - .withEndDate(LocalDate.of(2022, 7, 31)).build(); - Objective objectiveInvalid = Objective.Builder.builder().withId(null).withTitle("Start date is missing") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(invalidQuarter).build(); + Quarter invalidQuarter = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ-22/23-Q3") + .withEndDate(LocalDate.of(2022, 7, 31)) + .build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(null) + .withTitle("Start date is missing") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(invalidQuarter) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(objectiveInvalid)); + () -> validator.validateOnCreate(objectiveInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("StartDate", "GJ-22/23-Q3"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); @@ -211,14 +287,25 @@ void validateOnCreateShouldThrowExceptionWhenStartDateIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenEndDateIsNull() { - Quarter invalidQuarter = Quarter.Builder.builder().withId(1L).withLabel("GJ-22/23-Q3") - .withStartDate(LocalDate.of(2022, 4, 1)).build(); - Objective objectiveInvalid = Objective.Builder.builder().withId(null).withTitle("End date is missing") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(invalidQuarter).build(); + Quarter invalidQuarter = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ-22/23-Q3") + .withStartDate(LocalDate.of(2022, 4, 1)) + .build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(null) + .withTitle("End date is missing") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(invalidQuarter) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(objectiveInvalid)); + () -> validator.validateOnCreate(objectiveInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("EndDate", "GJ-22/23-Q3"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); @@ -239,7 +326,7 @@ void validateOnUpdateShouldBeSuccessfulWhenObjectiveIsValid() { @Test void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, null)); + () -> validator.validateOnUpdate(1L, null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Objective"))); @@ -251,7 +338,7 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, objectiveMinimal)); + () -> validator.validateOnUpdate(null, objectiveMinimal)); verify(validator, times(1)).throwExceptionWhenModelIsNull(objectiveMinimal); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -265,7 +352,7 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(7L, objective1)); + () -> validator.validateOnUpdate(7L, objective1)); verify(validator, times(1)).throwExceptionWhenModelIsNull(objective1); verify(validator, times(1)).throwExceptionWhenIdIsNull(objective1.getId()); @@ -280,14 +367,23 @@ void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { @ParameterizedTest @MethodSource("nameValidationArguments") void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String title, List expectedErrors) { - Objective objective = Objective.Builder.builder().withId(3L).withTitle(title).withCreatedBy(this.user) - .withTeam(this.team).withQuarter(this.quarter).withDescription("This is our description 2") - .withModifiedOn(LocalDateTime.MAX).withState(State.DRAFT).withModifiedBy(this.user) - .withCreatedOn(LocalDateTime.MAX).build(); + Objective objective = Objective.Builder + .builder() + .withId(3L) + .withTitle(title) + .withCreatedBy(this.user) + .withTeam(this.team) + .withQuarter(this.quarter) + .withDescription("This is our description 2") + .withModifiedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withModifiedBy(this.user) + .withCreatedOn(LocalDateTime.MAX) + .build(); when(objectivePersistenceService.findById(objective.getId())).thenReturn(objective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(3L, objective)); + () -> validator.validateOnUpdate(3L, objective)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -296,16 +392,22 @@ void validateOnUpdateShouldThrowExceptionWhenTitleIsInvalid(String title, List validator.validateOnUpdate(5L, objective)); - List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective"))); + () -> validator.validateOnUpdate(5L, objective)); + List expectedErrors = List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -314,12 +416,20 @@ void validateOnUpdateShouldThrowExceptionWhenAttrsAreMissing() { @Test void validateOnUpdateShouldThrowExceptionWhenAttrModifiedByIsNotSet() { - Objective objectiveInvalid = Objective.Builder.builder().withId(1L) - .withTitle("ModifiedBy is not null on create").withCreatedBy(user).withCreatedOn(LocalDateTime.MAX) - .withState(State.DRAFT).withTeam(team).withQuarter(quarter).withModifiedBy(null).build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(1L) + .withTitle("ModifiedBy is not null on create") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(quarter) + .withModifiedBy(null) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, objectiveInvalid)); + () -> validator.validateOnUpdate(1L, objectiveInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_SET", List.of("modifiedBy"))); @@ -330,14 +440,26 @@ void validateOnUpdateShouldThrowExceptionWhenAttrModifiedByIsNotSet() { @Test void validateOnUpdateShouldThrowExceptionWhenStartDateIsNull() { - Quarter invalidQuarter = Quarter.Builder.builder().withId(1L).withLabel("GJ-22/23-Q3") - .withEndDate(LocalDate.of(2022, 7, 31)).build(); - Objective objectiveInvalid = Objective.Builder.builder().withId(1L).withTitle("Start date is missing") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(invalidQuarter).withModifiedBy(user).build(); + Quarter invalidQuarter = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ-22/23-Q3") + .withEndDate(LocalDate.of(2022, 7, 31)) + .build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(1L) + .withTitle("Start date is missing") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(invalidQuarter) + .withModifiedBy(user) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, objectiveInvalid)); + () -> validator.validateOnUpdate(1L, objectiveInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("StartDate", "GJ-22/23-Q3"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); @@ -347,14 +469,26 @@ void validateOnUpdateShouldThrowExceptionWhenStartDateIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenEndDateIsNull() { - Quarter invalidQuarter = Quarter.Builder.builder().withId(1L).withLabel("GJ-22/23-Q3") - .withStartDate(LocalDate.of(2022, 4, 1)).build(); - Objective objectiveInvalid = Objective.Builder.builder().withId(1L).withTitle("End date is missing") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(invalidQuarter).withModifiedBy(user).build(); + Quarter invalidQuarter = Quarter.Builder + .builder() + .withId(1L) + .withLabel("GJ-22/23-Q3") + .withStartDate(LocalDate.of(2022, 4, 1)) + .build(); + Objective objectiveInvalid = Objective.Builder + .builder() + .withId(1L) + .withTitle("End date is missing") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(invalidQuarter) + .withModifiedBy(user) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, objectiveInvalid)); + () -> validator.validateOnUpdate(1L, objectiveInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("EndDate", "GJ-22/23-Q3"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); @@ -364,17 +498,32 @@ void validateOnUpdateShouldThrowExceptionWhenEndDateIsNull() { @Test void validateOnUpdateShouldThrowExceptionWheTeamHasChanged() { - Objective savedObjective = Objective.Builder.builder().withId(1L).withTitle("Team has changed") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(quarter).withModifiedBy(null).build(); - Objective updatedObjective = Objective.Builder.builder().withId(1L).withTitle("Team has changed") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT) - .withTeam(Team.Builder.builder().withId(2L).withName("other team").build()).withQuarter(quarter) - .withModifiedBy(user).build(); + Objective savedObjective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Team has changed") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(quarter) + .withModifiedBy(null) + .build(); + Objective updatedObjective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Team has changed") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(Team.Builder.builder().withId(2L).withName("other team").build()) + .withQuarter(quarter) + .withModifiedBy(user) + .build(); when(objectivePersistenceService.findById(savedObjective.getId())).thenReturn(savedObjective); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, updatedObjective)); + () -> validator.validateOnUpdate(1L, updatedObjective)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_CANNOT_CHANGE", List.of("Team", "Objective"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); @@ -385,14 +534,26 @@ void validateOnUpdateShouldThrowExceptionWheTeamHasChanged() { @ParameterizedTest @EnumSource(value = State.class, names = { "DRAFT" }, mode = EnumSource.Mode.EXCLUDE) void validateOnCreateShouldThrowExceptionWhenQuarterIsBacklogAndStateIsNotDraft(State state) { - Quarter backlogQuarter = Quarter.Builder.builder().withId(BACK_LOG_QUARTER_ID).withLabel(BACK_LOG_QUARTER_LABEL) - .withStartDate(null).withEndDate(null).build(); + Quarter backlogQuarter = Quarter.Builder + .builder() + .withId(BACK_LOG_QUARTER_ID) + .withLabel(BACK_LOG_QUARTER_LABEL) + .withStartDate(null) + .withEndDate(null) + .build(); - Objective invalidObjective = Objective.Builder.builder().withTitle("Invalid Objective").withCreatedBy(user) - .withCreatedOn(LocalDateTime.MAX).withState(state).withTeam(team).withQuarter(backlogQuarter).build(); + Objective invalidObjective = Objective.Builder + .builder() + .withTitle("Invalid Objective") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(state) + .withTeam(team) + .withQuarter(backlogQuarter) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(invalidObjective)); + () -> validator.validateOnCreate(invalidObjective)); List expectedErrors = List .of(new ErrorDto("ATTRIBUTE_MUST_BE_DRAFT", List.of("Objective", "Draft", state.toString()))); @@ -404,15 +565,28 @@ void validateOnCreateShouldThrowExceptionWhenQuarterIsBacklogAndStateIsNotDraft( @ParameterizedTest @EnumSource(value = State.class, names = { "DRAFT" }, mode = EnumSource.Mode.EXCLUDE) void validateOnUpdateShouldThrowExceptionWhenQuarterIsBacklogAndStateIsNotDraft(State state) { - Quarter backlogQuarter = Quarter.Builder.builder().withId(BACK_LOG_QUARTER_ID).withLabel(BACK_LOG_QUARTER_LABEL) - .withStartDate(null).withEndDate(null).build(); + Quarter backlogQuarter = Quarter.Builder + .builder() + .withId(BACK_LOG_QUARTER_ID) + .withLabel(BACK_LOG_QUARTER_LABEL) + .withStartDate(null) + .withEndDate(null) + .build(); - Objective invalidObjective = Objective.Builder.builder().withId(1L).withTitle("Invalid Objective") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(state).withTeam(team) - .withQuarter(backlogQuarter).withModifiedBy(user).build(); + Objective invalidObjective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Invalid Objective") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(state) + .withTeam(team) + .withQuarter(backlogQuarter) + .withModifiedBy(user) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, invalidObjective)); + () -> validator.validateOnUpdate(1L, invalidObjective)); List expectedErrors = List .of(new ErrorDto("ATTRIBUTE_MUST_BE_DRAFT", List.of("Objective", "Draft", state.toString()))); @@ -423,12 +597,25 @@ void validateOnUpdateShouldThrowExceptionWhenQuarterIsBacklogAndStateIsNotDraft( @Test void validateOnUpdateShouldPassWhenQuarterIsBacklogAndStateIsDraft() { - Quarter backlogQuarter = Quarter.Builder.builder().withId(BACK_LOG_QUARTER_ID).withLabel(BACK_LOG_QUARTER_LABEL) - .withStartDate(null).withEndDate(null).build(); + Quarter backlogQuarter = Quarter.Builder + .builder() + .withId(BACK_LOG_QUARTER_ID) + .withLabel(BACK_LOG_QUARTER_LABEL) + .withStartDate(null) + .withEndDate(null) + .build(); - Objective validObjective = Objective.Builder.builder().withId(1L).withTitle("Invalid Objective") - .withCreatedBy(user).withCreatedOn(LocalDateTime.MAX).withState(State.DRAFT).withTeam(team) - .withQuarter(backlogQuarter).withModifiedBy(user).build(); + Objective validObjective = Objective.Builder + .builder() + .withId(1L) + .withTitle("Invalid Objective") + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withState(State.DRAFT) + .withTeam(team) + .withQuarter(backlogQuarter) + .withModifiedBy(user) + .build(); assertDoesNotThrow(() -> validator.validateOnUpdate(1L, validObjective)); } @@ -444,7 +631,7 @@ void validateOnDeleteShouldBeSuccessfulWhenValidObjectiveId() { @Test void validateOnDeleteShouldThrowExceptionIfObjectiveIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Objective"))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/OverviewValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/OverviewValidationServiceTest.java index f61bbc48cd..742017d560 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/OverviewValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/OverviewValidationServiceTest.java @@ -1,16 +1,16 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.test.OverviewTestHelper.*; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static ch.puzzle.okr.test.OverviewTestHelper.*; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - @ExtendWith(MockitoExtension.class) class OverviewValidationServiceTest { @Mock diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/QuarterValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/QuarterValidationServiceTest.java index d47a98e53c..d5ba366f20 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/QuarterValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/QuarterValidationServiceTest.java @@ -1,10 +1,18 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Quarter; import ch.puzzle.okr.service.persistence.QuarterPersistenceService; import ch.puzzle.okr.test.TestHelper; +import java.time.LocalDate; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,15 +22,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.mock.mockito.MockBean; -import java.time.LocalDate; -import java.util.List; - -import static ch.puzzle.okr.Constants.BACK_LOG_QUARTER_LABEL; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @ExtendWith(MockitoExtension.class) class QuarterValidationServiceTest { @MockBean @@ -57,7 +56,8 @@ void throwExceptionWhenStartEndDateQuarterIsNullShouldThrowExceptionWhenStartDat // act + assert OkrResponseStatusException okrResponseStatusException = assertThrows(OkrResponseStatusException.class, - () -> QuarterValidationService.throwExceptionWhenStartEndDateQuarterIsNull(quarter)); + () -> QuarterValidationService + .throwExceptionWhenStartEndDateQuarterIsNull(quarter)); assertEquals(BAD_REQUEST, okrResponseStatusException.getStatusCode()); } @@ -72,7 +72,8 @@ void throwExceptionWhenStartEndDateQuarterIsNullShouldThrowExceptionWhenEndDateI // act + assert OkrResponseStatusException okrResponseStatusException = assertThrows(OkrResponseStatusException.class, - () -> QuarterValidationService.throwExceptionWhenStartEndDateQuarterIsNull(quarter)); + () -> QuarterValidationService + .throwExceptionWhenStartEndDateQuarterIsNull(quarter)); assertEquals(BAD_REQUEST, okrResponseStatusException.getStatusCode()); } @@ -100,7 +101,7 @@ void validateOnCreateShouldThrowException() { @Test void validateOnUpdateShouldThrowException() { Exception exception = assertThrows(IllegalCallerException.class, - () -> validator.validateOnUpdate(anyLong(), any())); + () -> validator.validateOnUpdate(anyLong(), any())); assertEquals("This method must not be called because there is no update of quarters", exception.getMessage()); } @@ -114,11 +115,12 @@ void validateOnGenerationShouldThrowExceptionWhenStartDateIsNull() { // act + assert OkrResponseStatusException okrResponseStatusException = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGeneration(quarter)); + () -> validator + .validateOnGeneration(quarter)); assertOkrResponseStatusException( // - okrResponseStatusException, // - List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("StartDate", "Any Label")))); + okrResponseStatusException, // + List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("StartDate", "Any Label")))); } @DisplayName("validateOnGeneration() should throw exception when EndDate is null") @@ -132,11 +134,12 @@ void validateOnGenerationShouldThrowExceptionWhenEndDateIsNull() { // act + assert OkrResponseStatusException okrResponseStatusException = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGeneration(quarter)); + () -> validator + .validateOnGeneration(quarter)); assertOkrResponseStatusException( // - okrResponseStatusException, // - List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("EndDate", "Any Label")))); + okrResponseStatusException, // + List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("EndDate", "Any Label")))); } @DisplayName("validateOnGeneration() should do nothing when both dates are not null") diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/TeamValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/TeamValidationServiceTest.java index 044a7b9a5c..cd4bb9a9b4 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/TeamValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/TeamValidationServiceTest.java @@ -1,10 +1,16 @@ package ch.puzzle.okr.service.validation; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Team; import ch.puzzle.okr.service.persistence.TeamPersistenceService; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,13 +23,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @ExtendWith(MockitoExtension.class) class TeamValidationServiceTest { @MockBean @@ -46,8 +45,12 @@ void setUp() { when(teamPersistenceService.findById(1L)).thenReturn(team1); when(teamPersistenceService.getModelName()).thenReturn("Team"); doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, - String.format("%s with id %s not found", teamPersistenceService.getModelName(), 2L))) - .when(teamPersistenceService).findById(2L); + String + .format("%s with id %s not found", + teamPersistenceService.getModelName(), + 2L))) + .when(teamPersistenceService) + .findById(2L); } @Spy @@ -65,7 +68,7 @@ void validateOnGetShouldBeSuccessfulWhenValidTeamId() { @Test void validateOnGetShouldThrowExceptionIfTeamIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Team"))); @@ -86,7 +89,7 @@ void validateOnDeleteShouldBeSuccessfulWhenValidTeamId() { @Test void validateOnDeleteShouldThrowExceptionIfTeamIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Team"))); @@ -99,7 +102,7 @@ void validateOnDeleteShouldThrowExceptionIfTeamIdIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(team1)); + () -> validator.validateOnCreate(team1)); verify(validator, times(1)).throwExceptionWhenIdIsNotNull(team1.getId()); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Team"))); @@ -112,7 +115,7 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { void validateOnCreateShouldThrowExceptionWhenTeamAlreadyExists() { BDDMockito.given(teamPersistenceService.findTeamsByName(anyString())).willReturn(List.of(team1)); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(teamWithIdNull)); + () -> validator.validateOnCreate(teamWithIdNull)); List expectedErrors = List.of(new ErrorDto("ALREADY_EXISTS_SAME_NAME", List.of("Team", "Team null"))); @@ -124,7 +127,7 @@ void validateOnCreateShouldThrowExceptionWhenTeamAlreadyExists() { @Test void validateOnCreateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); verify(validator, times(1)).throwExceptionWhenModelIsNull(null); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Team"))); @@ -136,12 +139,13 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenModelIsNameIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(teamWithoutName)); + () -> validator.validateOnCreate(teamWithoutName)); verify(validator, times(1)).throwExceptionWhenModelIsNull(teamWithoutName); verify(validator, times(1)).throwExceptionWhenIdIsNotNull(teamWithoutName.getId()); verify(validator, times(1)).validate(teamWithoutName); - List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("name", "Team")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("name", "Team"))); + List expectedErrors = List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("name", "Team")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("name", "Team"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); @@ -151,7 +155,9 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNameIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenModelIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(teamWithIdNull.getId(), teamWithIdNull)); + () -> validator + .validateOnUpdate(teamWithIdNull.getId(), + teamWithIdNull)); verify(validator, times(1)).throwExceptionWhenModelIsNull(teamWithIdNull); verify(validator, times(1)).throwExceptionWhenIdIsNull(teamWithIdNull.getId()); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Team"))); @@ -164,7 +170,7 @@ void validateOnUpdateShouldThrowExceptionWhenModelIdIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, null)); + () -> validator.validateOnUpdate(null, null)); verify(validator, times(1)).throwExceptionWhenModelIsNull(null); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Team"))); @@ -176,12 +182,15 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenModelIsNameIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(teamWithoutNameWithId.getId(), teamWithoutNameWithId)); + () -> validator + .validateOnUpdate(teamWithoutNameWithId.getId(), + teamWithoutNameWithId)); verify(validator, times(1)).throwExceptionWhenModelIsNull(teamWithoutNameWithId); verify(validator, times(1)).throwExceptionWhenIdIsNull(teamWithoutNameWithId.getId()); verify(validator, times(1)).validate(teamWithoutNameWithId); - List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("name", "Team")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("name", "Team"))); + List expectedErrors = List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("name", "Team")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("name", "Team"))); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/UserValidationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/UserValidationServiceTest.java index fbf55cb798..d229e06346 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/UserValidationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/UserValidationServiceTest.java @@ -1,10 +1,18 @@ package ch.puzzle.okr.service.validation; -import ch.puzzle.okr.test.TestHelper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.User; import ch.puzzle.okr.service.persistence.UserPersistenceService; +import ch.puzzle.okr.test.TestHelper; +import java.util.List; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,15 +29,6 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.web.server.ResponseStatusException; -import java.util.List; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - @ExtendWith(MockitoExtension.class) class UserValidationServiceTest { @MockBean @@ -43,17 +42,30 @@ class UserValidationServiceTest { @BeforeEach void setUp() { - user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); + user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); - userMinimal = User.Builder.builder().withFirstname("Max").withLastname("Mustermann") - .withEmail("max@mustermann.com").build(); + userMinimal = User.Builder + .builder() + .withFirstname("Max") + .withLastname("Mustermann") + .withEmail("max@mustermann.com") + .build(); when(userPersistenceService.findById(1L)).thenReturn(user); when(userPersistenceService.getModelName()).thenReturn("User"); doThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, - String.format("%s with id %s not found", userPersistenceService.getModelName(), 2L))) - .when(userPersistenceService).findById(2L); + String + .format("%s with id %s not found", + userPersistenceService.getModelName(), + 2L))) + .when(userPersistenceService) + .findById(2L); } @Spy @@ -61,59 +73,80 @@ void setUp() { private UserValidationService validator; private static Stream firstNameValidationArguments() { - return Stream.of( - arguments(StringUtils.repeat('1', 51), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), - arguments(StringUtils.repeat('1', 1), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), - arguments("", - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), - arguments(" ", - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), - arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("firstname", "User"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 51), + List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), + arguments(StringUtils.repeat('1', 1), + List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("firstname", "User", "2", "50")))), + arguments("", + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("firstname", "User", "2", "50")))), + arguments(" ", + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("firstname", "User", "2", "50")))), + arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")))), + arguments(null, + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("firstname", "User")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("firstname", "User"))))); } private static Stream lastNameValidationArguments() { - return Stream.of( - arguments(StringUtils.repeat('1', 51), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), - arguments(StringUtils.repeat('1', 1), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), - arguments("", - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), - arguments(" ", - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), - arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("lastname", "User"))))); + return Stream + .of(arguments(StringUtils.repeat('1', 51), + List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), + arguments(StringUtils.repeat('1', 1), + List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("lastname", "User", "2", "50")))), + arguments("", + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("lastname", "User", "2", "50")))), + arguments(" ", + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("lastname", "User", "2", "50")))), + arguments(" ", List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")))), + arguments(null, + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("lastname", "User")), + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("lastname", "User"))))); } private static Stream emailValidationArguments() { - return Stream.of( - arguments(("1".repeat(251)), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), - arguments(("1"), - List.of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")), - new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), - arguments((""), - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")))), - arguments((" "), - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), - new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")), - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")))), - arguments((" "), - List.of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), - new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), - arguments(null, List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("email", "User")), - new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User"))))); + return Stream + .of(arguments(("1".repeat(251)), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), + arguments(("1"), + List + .of(new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("email", "User", "2", "250")), + new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), + arguments((""), + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("email", "User", "2", "250")))), + arguments((" "), + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), + new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")), + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", + List.of("email", "User", "2", "250")))), + arguments((" "), + List + .of(new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User")), + new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User")))), + arguments(null, + List + .of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("email", "User")), + new ErrorDto("ATTRIBUTE_NOT_BLANK", List.of("email", "User"))))); } @Test @@ -127,7 +160,7 @@ void validateOnGetShouldBeSuccessfulWhenValidUserId() { @Test void validateOnGetShouldThrowExceptionIfUserIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "User"))); @@ -147,7 +180,7 @@ void validateOnGetOrCreateShouldBeSuccessful() { @Test void validateOnGetOrCreateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGetOrCreate(null)); + () -> validator.validateOnGetOrCreate(null)); verify(validator, times(1)).throwExceptionWhenModelIsNull(null); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("User"))); @@ -168,7 +201,7 @@ void validateOnCreateShouldBeSuccessfulWhenUserIsValid() { @Test void validateOnCreateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(null)); + () -> validator.validateOnCreate(null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("User"))); @@ -180,7 +213,7 @@ void validateOnCreateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(user)); + () -> validator.validateOnCreate(user)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "User"))); @@ -192,11 +225,15 @@ void validateOnCreateShouldThrowExceptionWhenIdIsNotNull() { @ParameterizedTest @MethodSource("firstNameValidationArguments") void validateOnCreateShouldThrowExceptionWhenFirstnameIsInvalid(String name, List errors) { - User user2 = User.Builder.builder().withEmail("max@mail.com").withFirstname(name).withLastname("lastname") + User user2 = User.Builder + .builder() + .withEmail("max@mail.com") + .withFirstname(name) + .withLastname("lastname") .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(user2)); + () -> validator.validateOnCreate(user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -206,11 +243,15 @@ void validateOnCreateShouldThrowExceptionWhenFirstnameIsInvalid(String name, Lis @ParameterizedTest @MethodSource("lastNameValidationArguments") void validateOnCreateShouldThrowExceptionWhenLastnameIsInvalid(String name, List errors) { - User user2 = User.Builder.builder().withEmail("max@mail.com").withFirstname("firstname").withLastname(name) + User user2 = User.Builder + .builder() + .withEmail("max@mail.com") + .withFirstname("firstname") + .withLastname(name) .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(user2)); + () -> validator.validateOnCreate(user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -220,11 +261,15 @@ void validateOnCreateShouldThrowExceptionWhenLastnameIsInvalid(String name, List @ParameterizedTest @MethodSource("emailValidationArguments") void validateOnCreateShouldThrowExceptionWhenEmailIsInvalid(String email, List errors) { - User user2 = User.Builder.builder().withEmail(email).withFirstname("firstname").withLastname("lastname") + User user2 = User.Builder + .builder() + .withEmail(email) + .withFirstname("firstname") + .withLastname("lastname") .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnCreate(user2)); + () -> validator.validateOnCreate(user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -233,10 +278,15 @@ void validateOnCreateShouldThrowExceptionWhenEmailIsInvalid(String email, List validator.validateOnCreate(userInvalid)); + () -> validator.validateOnCreate(userInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User"))); @@ -258,7 +308,7 @@ void validateOnUpdateShouldBeSuccessfulWhenUserIsValid() { @Test void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(1L, null)); + () -> validator.validateOnUpdate(1L, null)); List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("User"))); @@ -270,7 +320,7 @@ void validateOnUpdateShouldThrowExceptionWhenModelIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(null, userMinimal)); + () -> validator.validateOnUpdate(null, userMinimal)); verify(validator, times(1)).throwExceptionWhenModelIsNull(userMinimal); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); @@ -285,7 +335,7 @@ void validateOnUpdateShouldThrowExceptionWhenIdIsNull() { @Test void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(7L, user)); + () -> validator.validateOnUpdate(7L, user)); verify(validator, times(1)).throwExceptionWhenModelIsNull(user); verify(validator, times(1)).throwExceptionWhenIdIsNull(user.getId()); @@ -301,11 +351,16 @@ void validateOnUpdateShouldThrowExceptionWhenIdHasChanged() { @ParameterizedTest @MethodSource("firstNameValidationArguments") void validateOnUpdateShouldThrowExceptionWhenFirstnameIsInvalid(String name, List errors) { - User user2 = User.Builder.builder().withId(3L).withEmail("max@mail.com").withFirstname(name) - .withLastname("lastname").build(); + User user2 = User.Builder + .builder() + .withId(3L) + .withEmail("max@mail.com") + .withFirstname(name) + .withLastname("lastname") + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(3L, user2)); + () -> validator.validateOnUpdate(3L, user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -315,11 +370,16 @@ void validateOnUpdateShouldThrowExceptionWhenFirstnameIsInvalid(String name, Lis @ParameterizedTest @MethodSource("lastNameValidationArguments") void validateOnUpdateShouldThrowExceptionWhenLastnameIsInvalid(String name, List errors) { - User user2 = User.Builder.builder().withId(3L).withEmail("max@mail.com").withFirstname("firstname") - .withLastname(name).build(); + User user2 = User.Builder + .builder() + .withId(3L) + .withEmail("max@mail.com") + .withFirstname("firstname") + .withLastname(name) + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(3L, user2)); + () -> validator.validateOnUpdate(3L, user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -329,11 +389,16 @@ void validateOnUpdateShouldThrowExceptionWhenLastnameIsInvalid(String name, List @ParameterizedTest @MethodSource("emailValidationArguments") void validateOnUpdateShouldThrowExceptionWhenEmailIsInvalid(String email, List errors) { - User user2 = User.Builder.builder().withId(3L).withEmail(email).withFirstname("firstname") - .withLastname("lastname").build(); + User user2 = User.Builder + .builder() + .withId(3L) + .withEmail(email) + .withFirstname("firstname") + .withLastname("lastname") + .build(); OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnUpdate(3L, user2)); + () -> validator.validateOnUpdate(3L, user2)); assertEquals(BAD_REQUEST, exception.getStatusCode()); assertThat(errors).hasSameElementsAs(exception.getErrors()); @@ -342,10 +407,15 @@ void validateOnUpdateShouldThrowExceptionWhenEmailIsInvalid(String email, List validator.validateOnUpdate(3L, userInvalid)); + () -> validator.validateOnUpdate(3L, userInvalid)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_VALID", List.of("email", "User"))); @@ -364,7 +434,7 @@ void validateAuthorisationTokenShouldNotThrowError() { @Test void validateAuthorisationTokenShouldThrowErrorWhenNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateAuthorisationToken(null)); + () -> validator.validateAuthorisationToken(null)); List expectedErrors = List.of(new ErrorDto("TOKEN_NULL", List.of())); @@ -384,7 +454,7 @@ void validateOnDeleteShouldBeSuccessfulWhenValidObjectiveId() { @Test void validateOnDeleteShouldThrowExceptionIfObjectiveIdIsNull() { OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(null)); + () -> validator.validateOnGet(null)); verify(validator, times(1)).throwExceptionWhenIdIsNull(null); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "User"))); diff --git a/backend/src/test/java/ch/puzzle/okr/service/validation/ValidationBaseTest.java b/backend/src/test/java/ch/puzzle/okr/service/validation/ValidationBaseTest.java index c91cfddc1b..0b4b1318ad 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/validation/ValidationBaseTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/validation/ValidationBaseTest.java @@ -1,5 +1,9 @@ package ch.puzzle.okr.service.validation; +import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; import ch.puzzle.okr.models.Objective; @@ -8,6 +12,7 @@ import ch.puzzle.okr.repository.QuarterRepository; import ch.puzzle.okr.service.persistence.ObjectivePersistenceService; import ch.puzzle.okr.service.persistence.QuarterPersistenceService; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,12 +22,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.mock.mockito.MockBean; -import java.util.List; - -import static ch.puzzle.okr.test.AssertionHelper.assertOkrResponseStatusException; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class ValidationBaseTest { @MockBean @@ -62,7 +61,7 @@ void validateOnGetShouldThrowExceptionWhenIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnGet(id)); + () -> validator.validateOnGet(id)); // assert List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Quarter"))); @@ -93,7 +92,7 @@ void validateOnDeleteShouldThrowExceptionWhenIdIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validateOnDelete(id)); + () -> validator.validateOnDelete(id)); // assert List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NULL", List.of("ID", "Quarter"))); @@ -121,7 +120,7 @@ void throwExceptionWhenModelIsNullShouldThrowExceptionWhenModelIsNull() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.throwExceptionWhenModelIsNull(model)); + () -> validator.throwExceptionWhenModelIsNull(model)); // assert List expectedErrors = List.of(new ErrorDto("MODEL_NULL", List.of("Quarter"))); @@ -145,7 +144,7 @@ void throwExceptionWhenIdIsNotNullShouldThrowExceptionWhenIdIsNotNull() { // act OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.throwExceptionWhenIdIsNotNull(id)); + () -> validator.throwExceptionWhenIdIsNotNull(id)); // assert List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("ID", "Quarter"))); @@ -171,7 +170,8 @@ void throwExceptionWhenIdHasChangedShouldThrowExceptionWhenIdsAreNotEqual() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.throwExceptionWhenIdHasChanged(id, modelId)); + () -> validator + .throwExceptionWhenIdHasChanged(id, modelId)); // assert List expectedErrors = List @@ -201,7 +201,7 @@ void validateShouldThrowExceptionWhenWhenConstraintInModelClassIsViolated() { // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validator.validate(quarterWithNullLabel)); + () -> validator.validate(quarterWithNullLabel)); List expectedErrors = List.of(new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("label", "Quarter"))); assertOkrResponseStatusException(exception, expectedErrors); @@ -217,21 +217,23 @@ void validateShouldThrowExceptionWhenOneOfSeveralConstraintsInModelClassIsViolat // act + assert OkrResponseStatusException exception = assertThrows(OkrResponseStatusException.class, - () -> validatorWithSeveralConstraints.validate(objective)); - - List expectedErrors = List.of( // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective")), // - new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("quarter", "Objective")), // - new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")) // - ); + () -> validatorWithSeveralConstraints.validate(objective)); + + List expectedErrors = List + .of( // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("team", "Objective")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdBy", "Objective")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("createdOn", "Objective")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("state", "Objective")), // + new ErrorDto("ATTRIBUTE_NOT_NULL", List.of("quarter", "Objective")), // + new ErrorDto("ATTRIBUTE_SIZE_BETWEEN", List.of("title", "Objective", "2", "250")) // + ); assertOkrResponseStatusException(exception, expectedErrors); } static class DummyValidationService - extends ValidationBase { + extends + ValidationBase { public DummyValidationService(QuarterPersistenceService quarterPersistenceService) { super(quarterPersistenceService); @@ -247,7 +249,8 @@ public void validateOnUpdate(Long aLong, Quarter model) { } static class DummyValidationServiceWithSeveralConstraints - extends ValidationBase { + extends + ValidationBase { public DummyValidationServiceWithSeveralConstraints(ObjectivePersistenceService objectivePersistenceService) { super(objectivePersistenceService); diff --git a/backend/src/test/java/ch/puzzle/okr/test/AssertionHelper.java b/backend/src/test/java/ch/puzzle/okr/test/AssertionHelper.java index cb5e4e2322..401f52075f 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/AssertionHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/test/AssertionHelper.java @@ -1,27 +1,25 @@ package ch.puzzle.okr.test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + import ch.puzzle.okr.dto.ErrorDto; import ch.puzzle.okr.exception.OkrResponseStatusException; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.springframework.http.HttpStatus; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - public class AssertionHelper { public static void assertOkrResponseStatusException(OkrResponseStatusException exception, - List expectedErrors) { + List expectedErrors) { assertOkrResponseStatusException(BAD_REQUEST, exception, expectedErrors); } public static void assertOkrResponseStatusException(HttpStatus statusCode, OkrResponseStatusException exception, - List expectedErrors) { + List expectedErrors) { assertEquals(statusCode, exception.getStatusCode()); assertThat(expectedErrors).hasSameElementsAs(exception.getErrors()); diff --git a/backend/src/test/java/ch/puzzle/okr/test/CheckInTestHelpers.java b/backend/src/test/java/ch/puzzle/okr/test/CheckInTestHelpers.java index 9ec1fc258d..189ba7815f 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/CheckInTestHelpers.java +++ b/backend/src/test/java/ch/puzzle/okr/test/CheckInTestHelpers.java @@ -11,7 +11,6 @@ import ch.puzzle.okr.models.checkin.Zone; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; - import java.time.LocalDateTime; public class CheckInTestHelpers { @@ -29,9 +28,9 @@ public class CheckInTestHelpers { public static final String JSON_CHANGE_INFO = "changeinfo"; public static final String JSON_INITIATIVES = "initiatives"; public static final String JSON = "{\"" + JSON_CHANGE_INFO + "\":" + "\"" + CHANGE_INFO_1 + "\"" - + ", \"keyResultId\": 1}"; + + ", \"keyResultId\": 1}"; public static final String JSON_WITHOUT_KEY_RESULT_ID = "{\"" + JSON_CHANGE_INFO + "\":" + "\"" + CHANGE_INFO_1 - + "\"}"; + + "\"}"; public static final String JSON_PATH_ID = "$.id"; public static final String JSON_PATH_CHANGE_INFO = "$.changeInfo"; @@ -46,24 +45,58 @@ public class CheckInTestHelpers { /* Test entities */ static final Objective objective = Objective.Builder.builder().withId(1L).build(); - public static final CheckIn checkInMetric = CheckInMetric.Builder.builder().withValue(30D).withConfidence(5) - .withChangeInfo(CHANGE_INFO).withInitiatives(INITIATIVES) + public static final CheckIn checkInMetric = CheckInMetric.Builder + .builder() + .withValue(30D) + .withConfidence(5) + .withChangeInfo(CHANGE_INFO) + .withInitiatives(INITIATIVES) .withCreatedBy(User.Builder.builder().withId(1L).withFirstname("Frank").build()) - .withKeyResult(KeyResultMetric.Builder.builder().withBaseline(3.0).withStretchGoal(6.0).withId(8L) - .withObjective(objective).build()) + .withKeyResult(KeyResultMetric.Builder + .builder() + .withBaseline(3.0) + .withStretchGoal(6.0) + .withId(8L) + .withObjective(objective) + .build()) .build(); - public static final CheckIn checkInOrdinal = CheckInOrdinal.Builder.builder().withZone(Zone.COMMIT).withId(4L) + public static final CheckIn checkInOrdinal = CheckInOrdinal.Builder + .builder() + .withZone(Zone.COMMIT) + .withId(4L) .withCreatedBy(User.Builder.builder().withId(2L).withFirstname("Robert").build()) - .withCreatedOn(LocalDateTime.MAX).withChangeInfo(CHANGE_INFO).withInitiatives(INITIATIVES) - .withKeyResult( - KeyResultOrdinal.Builder.builder().withCommitZone("Baum").withTargetZone("Wald").withId(9L).build()) + .withCreatedOn(LocalDateTime.MAX) + .withChangeInfo(CHANGE_INFO) + .withInitiatives(INITIATIVES) + .withKeyResult(KeyResultOrdinal.Builder + .builder() + .withCommitZone("Baum") + .withTargetZone("Wald") + .withId(9L) + .build()) .build(); /* Test DTOs */ - public static final CheckInDto checkInMetricDto = new CheckInMetricDto(5L, 1, CHANGE_INFO_1, INITIATIVES_1, 6, 1L, - LocalDateTime.MAX, LocalDateTime.MAX, 46D, true); - public static final CheckInDto checkInOrdinalDto = new CheckInOrdinalDto(4L, 1, CHANGE_INFO_2, INITIATIVES_2, 5, 2L, - LocalDateTime.MAX, LocalDateTime.MAX, Zone.COMMIT, true); + public static final CheckInDto checkInMetricDto = new CheckInMetricDto(5L, + 1, + CHANGE_INFO_1, + INITIATIVES_1, + 6, + 1L, + LocalDateTime.MAX, + LocalDateTime.MAX, + 46D, + true); + public static final CheckInDto checkInOrdinalDto = new CheckInOrdinalDto(4L, + 1, + CHANGE_INFO_2, + INITIATIVES_2, + 5, + 2L, + LocalDateTime.MAX, + LocalDateTime.MAX, + Zone.COMMIT, + true); public static final String CHECK_IN_METRIC_JSON = """ { diff --git a/backend/src/test/java/ch/puzzle/okr/test/KeyResultTestHelpers.java b/backend/src/test/java/ch/puzzle/okr/test/KeyResultTestHelpers.java index bdb71c1a08..ce37dc45b4 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/KeyResultTestHelpers.java +++ b/backend/src/test/java/ch/puzzle/okr/test/KeyResultTestHelpers.java @@ -1,5 +1,8 @@ package ch.puzzle.okr.test; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; +import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; + import ch.puzzle.okr.dto.checkin.CheckInDto; import ch.puzzle.okr.dto.checkin.CheckInMetricDto; import ch.puzzle.okr.dto.keyresult.*; @@ -12,14 +15,10 @@ import ch.puzzle.okr.models.keyresult.KeyResult; import ch.puzzle.okr.models.keyresult.KeyResultMetric; import ch.puzzle.okr.models.keyresult.KeyResultOrdinal; - import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC; -import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL; - public class KeyResultTestHelpers { public static final String DESCRIPTION = "Description"; @@ -78,41 +77,120 @@ public class KeyResultTestHelpers { static final String INITIATIVES_2 = "Initiatives2"; static final String CHANGE_INFO_1 = "Changeinfo1"; static final String CHANGE_INFO_2 = "Changeinfo2"; - public static final User user = User.Builder.builder().withId(1L).withFirstname("Bob").withLastname("Kaufmann") - .withEmail("kaufmann@puzzle.ch").build(); - public static final KeyResult metricKeyResult = KeyResultMetric.Builder.builder().withId(5L).withTitle(TITLE) + public static final User user = User.Builder + .builder() + .withId(1L) + .withFirstname("Bob") + .withLastname("Kaufmann") + .withEmail("kaufmann@puzzle.ch") + .build(); + public static final KeyResult metricKeyResult = KeyResultMetric.Builder + .builder() + .withId(5L) + .withTitle(TITLE) + .build(); + public static final CheckIn checkIn1 = CheckInMetric.Builder + .builder() + .withValue(23D) + .withId(1L) + .withKeyResult(metricKeyResult) + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withChangeInfo(CHANGE_INFO_1) + .withInitiatives(INITIATIVES_1) .build(); - public static final CheckIn checkIn1 = CheckInMetric.Builder.builder().withValue(23D).withId(1L) - .withKeyResult(metricKeyResult).withCreatedBy(user).withCreatedOn(LocalDateTime.MAX) - .withChangeInfo(CHANGE_INFO_1).withInitiatives(INITIATIVES_1).build(); - public static final CheckIn checkIn2 = CheckInMetric.Builder.builder().withValue(12D).withId(4L) - .withKeyResult(metricKeyResult).withCreatedBy(user).withCreatedOn(LocalDateTime.MAX) - .withChangeInfo(CHANGE_INFO_2).withInitiatives(INITIATIVES_2).build(); - public static final CheckInDto checkInDto1 = new CheckInMetricDto(1L, 1, CHANGE_INFO_1, INITIATIVES_1, 6, - metricKeyResult.getId(), LocalDateTime.MAX, LocalDateTime.MAX, 23D, true); - public static final CheckInDto checkInDto2 = new CheckInMetricDto(4L, 1, CHANGE_INFO_2, INITIATIVES_2, 5, - metricKeyResult.getId(), LocalDateTime.MAX, LocalDateTime.MAX, 12D, true); + public static final CheckIn checkIn2 = CheckInMetric.Builder + .builder() + .withValue(12D) + .withId(4L) + .withKeyResult(metricKeyResult) + .withCreatedBy(user) + .withCreatedOn(LocalDateTime.MAX) + .withChangeInfo(CHANGE_INFO_2) + .withInitiatives(INITIATIVES_2) + .build(); + public static final CheckInDto checkInDto1 = new CheckInMetricDto(1L, + 1, + CHANGE_INFO_1, + INITIATIVES_1, + 6, + metricKeyResult.getId(), + LocalDateTime.MAX, + LocalDateTime.MAX, + 23D, + true); + public static final CheckInDto checkInDto2 = new CheckInMetricDto(4L, + 1, + CHANGE_INFO_2, + INITIATIVES_2, + 5, + metricKeyResult.getId(), + LocalDateTime.MAX, + LocalDateTime.MAX, + 12D, + true); public static final KeyResultUserDto keyResultUserDto = new KeyResultUserDto(1L, FIRSTNAME, LASTNAME); - public static final KeyResultQuarterDto keyResultQuarterDto = new KeyResultQuarterDto(1L, QUARTER_LABEL, - LocalDate.MIN, LocalDate.MAX); - public static final KeyResultLastCheckInMetricDto keyResultLastCheckInDto = new KeyResultLastCheckInMetricDto(1L, 1, - 4.0, 6, LocalDateTime.MIN, CHANGE_INFO_1, INITIATIVES_1); - public static final KeyResultLastCheckInOrdinalDto keyResultLastCheckInOrdinalDto = new KeyResultLastCheckInOrdinalDto( - 1L, 1, LAST_CHECK_IN_ZONE, 6, LocalDateTime.MIN, CHANGE_INFO_2, INITIATIVES_2); + public static final KeyResultQuarterDto keyResultQuarterDto = new KeyResultQuarterDto(1L, + QUARTER_LABEL, + LocalDate.MIN, + LocalDate.MAX); + public static final KeyResultLastCheckInMetricDto keyResultLastCheckInDto = new KeyResultLastCheckInMetricDto(1L, + 1, + 4.0, + 6, + LocalDateTime.MIN, + CHANGE_INFO_1, + INITIATIVES_1); + public static final KeyResultLastCheckInOrdinalDto keyResultLastCheckInOrdinalDto = new KeyResultLastCheckInOrdinalDto(1L, + 1, + LAST_CHECK_IN_ZONE, + 6, + LocalDateTime.MIN, + CHANGE_INFO_2, + INITIATIVES_2); public static final KeyResultObjectiveDto keyResultObjectiveDto = new KeyResultObjectiveDto(1L, - OBJECTIVE_STATE_ONGOING, keyResultQuarterDto); + OBJECTIVE_STATE_ONGOING, + keyResultQuarterDto); - public static final KeyResultMetricDto keyResultMetricDto = new KeyResultMetricDto(5L, 1, KEY_RESULT_TYPE_METRIC, - TITLE, DESCRIPTION, 1.0, 5.0, KEY_RESULT_UNIT, keyResultUserDto, keyResultObjectiveDto, - keyResultLastCheckInDto, LocalDateTime.MIN, LocalDateTime.MAX, true, List.of()); - public static final KeyResultOrdinalDto keyResultOrdinalDto = new KeyResultOrdinalDto(5L, 1, - KEY_RESULT_TYPE_ORDINAL, TITLE, DESCRIPTION, COMMIT_ZONE, TARGET_ZONE, STRETCH_ZONE, keyResultUserDto, - keyResultObjectiveDto, keyResultLastCheckInOrdinalDto, LocalDateTime.MIN, LocalDateTime.MAX, true, - List.of()); + public static final KeyResultMetricDto keyResultMetricDto = new KeyResultMetricDto(5L, + 1, + KEY_RESULT_TYPE_METRIC, + TITLE, + DESCRIPTION, + 1.0, + 5.0, + KEY_RESULT_UNIT, + keyResultUserDto, + keyResultObjectiveDto, + keyResultLastCheckInDto, + LocalDateTime.MIN, + LocalDateTime.MAX, + true, + List.of()); + public static final KeyResultOrdinalDto keyResultOrdinalDto = new KeyResultOrdinalDto(5L, + 1, + KEY_RESULT_TYPE_ORDINAL, + TITLE, + DESCRIPTION, + COMMIT_ZONE, + TARGET_ZONE, + STRETCH_ZONE, + keyResultUserDto, + keyResultObjectiveDto, + keyResultLastCheckInOrdinalDto, + LocalDateTime.MIN, + LocalDateTime.MAX, + true, + List.of()); public static final Objective objective = Objective.Builder.builder().withId(5L).withTitle("Objective 1").build(); - public static final KeyResult ordinalKeyResult = KeyResultOrdinal.Builder.builder().withId(3L) - .withTitle("Keyresult 2").withOwner(user).withObjective(objective).build(); + public static final KeyResult ordinalKeyResult = KeyResultOrdinal.Builder + .builder() + .withId(3L) + .withTitle("Keyresult 2") + .withOwner(user) + .withObjective(objective) + .build(); public static final String CREATE_BODY_METRIC = """ { diff --git a/backend/src/test/java/ch/puzzle/okr/test/SpringIntegrationTest.java b/backend/src/test/java/ch/puzzle/okr/test/SpringIntegrationTest.java index 2fe500d842..b3cf7c9ee6 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/SpringIntegrationTest.java +++ b/backend/src/test/java/ch/puzzle/okr/test/SpringIntegrationTest.java @@ -1,11 +1,10 @@ package ch.puzzle.okr.test; +import java.lang.annotation.*; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; -import java.lang.annotation.*; - @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented diff --git a/backend/src/test/java/ch/puzzle/okr/test/TestHelper.java b/backend/src/test/java/ch/puzzle/okr/test/TestHelper.java index c09fa3994b..fcfc6d1345 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/TestHelper.java +++ b/backend/src/test/java/ch/puzzle/okr/test/TestHelper.java @@ -8,8 +8,6 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.security.oauth2.jwt.Jwt; - import java.io.IOException; import java.time.Instant; import java.util.ArrayList; @@ -18,6 +16,7 @@ import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.security.oauth2.jwt.Jwt; public class TestHelper { private TestHelper() { @@ -30,7 +29,12 @@ private TestHelper() { private static final String EMAIL = "kaufmann@puzzle.ch"; public static User defaultUser(Long id) { - return User.Builder.builder().withId(id).withFirstname(FIRSTNAME).withLastname(LASTNAME).withEmail(EMAIL) + return User.Builder + .builder() + .withId(id) + .withFirstname(FIRSTNAME) + .withLastname(LASTNAME) + .withEmail(EMAIL) .build(); } @@ -42,12 +46,16 @@ public static User defaultOkrChampion(Long id) { public static User defaultUserWithTeams(Long userId, List adminTeams, List memberTeams) { var user = defaultUser(userId); - var adminUserTeams = adminTeams.stream() + var adminUserTeams = adminTeams + .stream() .map(t -> UserTeam.Builder.builder().withTeamAdmin(true).withTeam(t).withUser(user).build()); - var memberUserTeams = memberTeams.stream() + var memberUserTeams = memberTeams + .stream() .map(t -> UserTeam.Builder.builder().withTeam(t).withUser(user).build()); - user.setUserTeamList( - Stream.concat(adminUserTeams, memberUserTeams).collect(Collectors.toCollection(ArrayList::new))); + user + .setUserTeamList(Stream + .concat(adminUserTeams, memberUserTeams) + .collect(Collectors.toCollection(ArrayList::new))); return user; } @@ -64,13 +72,14 @@ public static AuthorizationUser defaultAuthorizationUser() { } public static AuthorizationUser mockAuthorizationUser(User user) { - return mockAuthorizationUser(user.getId(), user.getFirstname(), user.getLastname(), user.getEmail(), - user.isOkrChampion()); + return mockAuthorizationUser(user + .getId(), user.getFirstname(), user.getLastname(), user.getEmail(), user.isOkrChampion()); } public static AuthorizationUser mockAuthorizationUser(Long id, String firstname, String lastname, String email, - boolean isOkrChampion) { - User user = User.Builder.builder() // + boolean isOkrChampion) { + User user = User.Builder + .builder() // .withId(id) // .withFirstname(firstname) // .withLastname(lastname) // diff --git a/backend/src/test/java/ch/puzzle/okr/test/dto/builder/ObjectiveDtoBuilder.java b/backend/src/test/java/ch/puzzle/okr/test/dto/builder/ObjectiveDtoBuilder.java index b3f7e90638..c8a2b55344 100644 --- a/backend/src/test/java/ch/puzzle/okr/test/dto/builder/ObjectiveDtoBuilder.java +++ b/backend/src/test/java/ch/puzzle/okr/test/dto/builder/ObjectiveDtoBuilder.java @@ -2,7 +2,6 @@ import ch.puzzle.okr.dto.ObjectiveDto; import ch.puzzle.okr.models.State; - import java.time.LocalDateTime; public class ObjectiveDtoBuilder { @@ -81,8 +80,17 @@ public ObjectiveDtoBuilder withWriteable(boolean writeable) { } public ObjectiveDto build() { - return new ObjectiveDto(id, version, title, teamId, quarterId, quarterLabel, description, state, createdOn, - modifiedOn, writeable); + return new ObjectiveDto(id, + version, + title, + teamId, + quarterId, + quarterLabel, + description, + state, + createdOn, + modifiedOn, + writeable); } } diff --git a/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeChecker.java b/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeChecker.java index d7ec5e387a..7b997bd5d4 100644 --- a/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeChecker.java +++ b/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeChecker.java @@ -1,7 +1,6 @@ package ch.puzzle.okr.util.quarter.check; import ch.puzzle.okr.models.Quarter; - import java.time.LocalDate; public class QuarterRangeChecker { diff --git a/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeCheckerTest.java b/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeCheckerTest.java index 8dbf76d0a1..6b65465213 100644 --- a/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeCheckerTest.java +++ b/backend/src/test/java/ch/puzzle/okr/util/quarter/check/QuarterRangeCheckerTest.java @@ -1,14 +1,13 @@ package ch.puzzle.okr.util.quarter.check; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import ch.puzzle.okr.models.Quarter; +import java.time.LocalDate; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.time.LocalDate; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - public class QuarterRangeCheckerTest { @DisplayName("nowIsInQuarter() should return false if Quarter is null") @@ -103,7 +102,8 @@ void nowIsInQuarterShouldReturnFalseIfNowIsAfterQuarterEndDate() { } private Quarter quarter(LocalDate startDate, LocalDate endDate) { - return Quarter.Builder.builder() // + return Quarter.Builder + .builder() // .withStartDate(startDate) // .withEndDate(endDate) // .build(); diff --git a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuarterLabelTest.java b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuarterLabelTest.java index 8d3d466546..2d4b3be6f0 100644 --- a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuarterLabelTest.java +++ b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuarterLabelTest.java @@ -1,15 +1,14 @@ package ch.puzzle.okr.util.quarter.generate; +import static org.junit.jupiter.api.Assertions.*; + +import java.time.LocalDate; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.time.LocalDate; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - public class QuarterLabelTest { @DisplayName("label() should return label with year and quarter info") @@ -21,34 +20,35 @@ void labelShouldReturnLabelWithYearAndQuarterInfo(LocalDate date, String expecte } private static Stream datesAndLabels() { - return Stream.of( // - Arguments.of(LocalDate.of(2024, 7, 1), "GJ 24/25-Q1"), - Arguments.of(LocalDate.of(2024, 7, 2), "GJ 24/25-Q1"), - Arguments.of(LocalDate.of(2024, 7, 15), "GJ 24/25-Q1"), - Arguments.of(LocalDate.of(2024, 9, 15), "GJ 24/25-Q1"), - Arguments.of(LocalDate.of(2024, 9, 29), "GJ 24/25-Q1"), - Arguments.of(LocalDate.of(2024, 9, 30), "GJ 24/25-Q1"), - - Arguments.of(LocalDate.of(2024, 10, 1), "GJ 24/25-Q2"), - Arguments.of(LocalDate.of(2024, 10, 2), "GJ 24/25-Q2"), - Arguments.of(LocalDate.of(2024, 10, 15), "GJ 24/25-Q2"), - Arguments.of(LocalDate.of(2024, 12, 15), "GJ 24/25-Q2"), - Arguments.of(LocalDate.of(2024, 12, 30), "GJ 24/25-Q2"), - Arguments.of(LocalDate.of(2024, 12, 31), "GJ 24/25-Q2"), - - Arguments.of(LocalDate.of(2024, 1, 1), "GJ 23/24-Q3"), - Arguments.of(LocalDate.of(2024, 1, 2), "GJ 23/24-Q3"), - Arguments.of(LocalDate.of(2024, 1, 15), "GJ 23/24-Q3"), - Arguments.of(LocalDate.of(2024, 3, 15), "GJ 23/24-Q3"), - Arguments.of(LocalDate.of(2024, 3, 30), "GJ 23/24-Q3"), - Arguments.of(LocalDate.of(2024, 3, 31), "GJ 23/24-Q3"), - - Arguments.of(LocalDate.of(2024, 4, 1), "GJ 23/24-Q4"), - Arguments.of(LocalDate.of(2024, 4, 2), "GJ 23/24-Q4"), - Arguments.of(LocalDate.of(2024, 4, 15), "GJ 23/24-Q4"), - Arguments.of(LocalDate.of(2024, 6, 15), "GJ 23/24-Q4"), - Arguments.of(LocalDate.of(2024, 6, 29), "GJ 23/24-Q4"), - Arguments.of(LocalDate.of(2024, 6, 30), "GJ 23/24-Q4")); + return Stream + .of( // + Arguments.of(LocalDate.of(2024, 7, 1), "GJ 24/25-Q1"), + Arguments.of(LocalDate.of(2024, 7, 2), "GJ 24/25-Q1"), + Arguments.of(LocalDate.of(2024, 7, 15), "GJ 24/25-Q1"), + Arguments.of(LocalDate.of(2024, 9, 15), "GJ 24/25-Q1"), + Arguments.of(LocalDate.of(2024, 9, 29), "GJ 24/25-Q1"), + Arguments.of(LocalDate.of(2024, 9, 30), "GJ 24/25-Q1"), + + Arguments.of(LocalDate.of(2024, 10, 1), "GJ 24/25-Q2"), + Arguments.of(LocalDate.of(2024, 10, 2), "GJ 24/25-Q2"), + Arguments.of(LocalDate.of(2024, 10, 15), "GJ 24/25-Q2"), + Arguments.of(LocalDate.of(2024, 12, 15), "GJ 24/25-Q2"), + Arguments.of(LocalDate.of(2024, 12, 30), "GJ 24/25-Q2"), + Arguments.of(LocalDate.of(2024, 12, 31), "GJ 24/25-Q2"), + + Arguments.of(LocalDate.of(2024, 1, 1), "GJ 23/24-Q3"), + Arguments.of(LocalDate.of(2024, 1, 2), "GJ 23/24-Q3"), + Arguments.of(LocalDate.of(2024, 1, 15), "GJ 23/24-Q3"), + Arguments.of(LocalDate.of(2024, 3, 15), "GJ 23/24-Q3"), + Arguments.of(LocalDate.of(2024, 3, 30), "GJ 23/24-Q3"), + Arguments.of(LocalDate.of(2024, 3, 31), "GJ 23/24-Q3"), + + Arguments.of(LocalDate.of(2024, 4, 1), "GJ 23/24-Q4"), + Arguments.of(LocalDate.of(2024, 4, 2), "GJ 23/24-Q4"), + Arguments.of(LocalDate.of(2024, 4, 15), "GJ 23/24-Q4"), + Arguments.of(LocalDate.of(2024, 6, 15), "GJ 23/24-Q4"), + Arguments.of(LocalDate.of(2024, 6, 29), "GJ 23/24-Q4"), + Arguments.of(LocalDate.of(2024, 6, 30), "GJ 23/24-Q4")); } } diff --git a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuartersTest.java b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuartersTest.java index 43d7aca711..cb33187b06 100644 --- a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuartersTest.java +++ b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/QuartersTest.java @@ -1,24 +1,23 @@ package ch.puzzle.okr.util.quarter.generate; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.time.LocalDate; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.time.LocalDate; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class QuartersTest { @DisplayName("currentQuarter() should find current quarter for now and 12 months in future") @ParameterizedTest @MethodSource("futureDatesAndLabels") void currentQuarterShouldFindCurrentQuarterForNowAnd12MonthsInFuture(LocalDate date, String expectedLabelFirstYear, - String expectedLabelSecondYear) { + String expectedLabelSecondYear) { // arrange Quarters nowQuarters = new Quarters(date.getYear()); @@ -36,66 +35,80 @@ void currentQuarterShouldFindCurrentQuarterForNowAnd12MonthsInFuture(LocalDate d } private static Stream futureDatesAndLabels() { - return Stream.of( // - Arguments.of( // - LocalDate.of(2024, 7, 15), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), - Arguments.of( // - LocalDate.of(2024, 8, 15), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), - Arguments.of( // - LocalDate.of(2024, 9, 15), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), - Arguments.of( // - LocalDate.of(2024, 10, 15), // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), - Arguments.of( // - LocalDate.of(2024, 11, 15), // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), - Arguments.of( // - LocalDate.of(2024, 12, 15), // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), - Arguments.of( // - LocalDate.of(2025, 1, 15), // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), - Arguments.of( // - LocalDate.of(2025, 2, 15), // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), - Arguments.of( // - LocalDate.of(2025, 3, 15), // - "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), - Arguments.of( // - LocalDate.of(2025, 4, 15), // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // - "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), - Arguments.of( // - LocalDate.of(2025, 5, 15), // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // - "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), - Arguments.of( // - LocalDate.of(2025, 6, 15), // - "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // - "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), - Arguments.of( // - LocalDate.of(2025, 7, 15), // - "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')", // - "('GJ 25/26-Q2', '2025-10-01', '2025-12-31')")); + return Stream + .of( // + Arguments + .of( // + LocalDate.of(2024, 7, 15), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), + Arguments + .of( // + LocalDate.of(2024, 8, 15), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), + Arguments + .of( // + LocalDate.of(2024, 9, 15), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')"), + Arguments + .of( // + LocalDate.of(2024, 10, 15), // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), + Arguments + .of( // + LocalDate.of(2024, 11, 15), // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), + Arguments + .of( // + LocalDate.of(2024, 12, 15), // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')", // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')"), + Arguments + .of( // + LocalDate.of(2025, 1, 15), // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), + Arguments + .of( // + LocalDate.of(2025, 2, 15), // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), + Arguments + .of( // + LocalDate.of(2025, 3, 15), // + "('GJ 24/25-Q3', '2025-01-01', '2025-03-31')", // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')"), + Arguments + .of( // + LocalDate.of(2025, 4, 15), // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // + "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), + Arguments + .of( // + LocalDate.of(2025, 5, 15), // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // + "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), + Arguments + .of( // + LocalDate.of(2025, 6, 15), // + "('GJ 24/25-Q4', '2025-04-01', '2025-06-30')", // + "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')"), + Arguments + .of( // + LocalDate.of(2025, 7, 15), // + "('GJ 25/26-Q1', '2025-07-01', '2025-09-30')", // + "('GJ 25/26-Q2', '2025-10-01', '2025-12-31')")); } @DisplayName("currentQuarter() should find current quarter for now and 7 months in past") @ParameterizedTest @MethodSource("pastDatesAndLabels") void currentQuarterShouldFindCurrentQuarterForNowAnd7MonthsInPast(LocalDate date, String expectedLabelFirstYear, - String expectedLabelSecondYear) { + String expectedLabelSecondYear) { // arrange Quarters nowQuarters = new Quarters(date.getYear()); @@ -113,39 +126,48 @@ void currentQuarterShouldFindCurrentQuarterForNowAnd7MonthsInPast(LocalDate date } private static Stream pastDatesAndLabels() { - return Stream.of( // - Arguments.of( // - LocalDate.of(2023, 12, 15), // - "('GJ 23/24-Q2', '2023-10-01', '2023-12-31')", // - "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')"), - Arguments.of( // - LocalDate.of(2024, 1, 15), // - "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), - Arguments.of( // - LocalDate.of(2024, 2, 15), // - "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), - Arguments.of( // - LocalDate.of(2024, 3, 15), // - "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), - Arguments.of( // - LocalDate.of(2024, 4, 15), // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), - Arguments.of( // - LocalDate.of(2024, 5, 15), // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), - Arguments.of( // - LocalDate.of(2024, 6, 15), // - "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), - Arguments.of( // - LocalDate.of(2024, 7, 15), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // - "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')")); + return Stream + .of( // + Arguments + .of( // + LocalDate.of(2023, 12, 15), // + "('GJ 23/24-Q2', '2023-10-01', '2023-12-31')", // + "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')"), + Arguments + .of( // + LocalDate.of(2024, 1, 15), // + "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), + Arguments + .of( // + LocalDate.of(2024, 2, 15), // + "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), + Arguments + .of( // + LocalDate.of(2024, 3, 15), // + "('GJ 23/24-Q3', '2024-01-01', '2024-03-31')", // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')"), + Arguments + .of( // + LocalDate.of(2024, 4, 15), // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), + Arguments + .of( // + LocalDate.of(2024, 5, 15), // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), + Arguments + .of( // + LocalDate.of(2024, 6, 15), // + "('GJ 23/24-Q4', '2024-04-01', '2024-06-30')", // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), + Arguments + .of( // + LocalDate.of(2024, 7, 15), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')", // + "('GJ 24/25-Q2', '2024-10-01', '2024-12-31')")); } @DisplayName("currentQuarter() should throw exception if no matching quarter is found for now") @@ -159,7 +181,7 @@ void currentQuarterShouldThrowExceptionIfNoMatchingQuarterIsFoundForNow() { // act RuntimeException exception = assertThrows(RuntimeException.class, - () -> allQuartersOfCurrentYear.currentQuarter(in2Years)); + () -> allQuartersOfCurrentYear.currentQuarter(in2Years)); // assert assertEquals(RuntimeException.class, exception.getClass()); @@ -181,13 +203,16 @@ void currentQuarterShouldFindCurrentQuarterForBoundaryDates(LocalDate date, Stri } private static Stream boundaryDatesAndLabels() { - return Stream.of( // - Arguments.of( // - LocalDate.of(2024, 7, 1), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), // - Arguments.of( // - LocalDate.of(2024, 9, 30), // - "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')") // - ); + return Stream + .of( // + Arguments + .of( // + LocalDate.of(2024, 7, 1), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')"), // + Arguments + .of( // + LocalDate.of(2024, 9, 30), // + "('GJ 24/25-Q1', '2024-07-01', '2024-09-30')") // + ); } } diff --git a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunctionTest.java b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunctionTest.java index 232c7c1337..41fa7e0cfa 100644 --- a/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunctionTest.java +++ b/backend/src/test/java/ch/puzzle/okr/util/quarter/generate/h2/QuarterFunctionTest.java @@ -1,11 +1,11 @@ package ch.puzzle.okr.util.quarter.generate.h2; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static ch.puzzle.okr.util.quarter.generate.h2.QuarterFunction.*; import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + public class QuarterFunctionTest { @DisplayName("QuarterFunction should return correct current quarter data") @@ -16,9 +16,9 @@ void quarterFunctionShouldReturnCorrectCurrentQuarterData() { // act String currentQuarter = "(2, " // - + currentQuarterLabel() + ", " // - + currentQuarterStartDate() + ", " // - + currentQuarterEndDate() + ")"; + + currentQuarterLabel() + ", " // + + currentQuarterStartDate() + ", " // + + currentQuarterEndDate() + ")"; // assert String expectedCurrent = "(2, GJ 24/25-Q2, 2024-10-01, 2024-12-31)"; @@ -33,9 +33,9 @@ void quarterFunctionShouldReturnCorrectNextQuarterData() { // act String nextQuarter = "(3, " // - + nextQuarterLabel() + ", " // - + nextQuarterStartDate() + ", " // - + nextQuarterEndDate() + ")"; + + nextQuarterLabel() + ", " // + + nextQuarterStartDate() + ", " // + + nextQuarterEndDate() + ")"; // assert String expectedNext = "(3, GJ 24/25-Q3, 2025-01-01, 2025-03-31)"; diff --git a/frontend/.prettierrc b/frontend/.prettierrc index cc9131084c..fa51da29e7 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,6 +1,6 @@ { - "trailingComma": "es5", - "tabWidth": 2, - "semi": false, - "singleQuote": true, + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true } diff --git a/frontend/README.md b/frontend/README.md index 79ee611146..5c0712d9b5 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -30,7 +30,6 @@ Build: ## Formatting - We use **EsLint** and a variety of plugins to format html and ts files: https://eslint.org/ @@ -48,16 +47,16 @@ Open the html file in browser and you get a beautiful overview ## Cypress Tests - local setup - - start local Docker `docker-compose up` - - start local Server: `OkrApplication-E2E` - - start local Client: `npm run start` + - start local Docker `docker-compose up` + - start local Server: `OkrApplication-E2E` + - start local Client: `npm run start` - run selected Tests - - npm run `npm run cypress:open` - - in Cypress App, select `E2E Testing` and `Chrome` as Browser + - npm run `npm run cypress:open` + - in Cypress App, select `E2E Testing` and `Chrome` as Browser - run all tests - - npm run `npm run cypress:run` - - in Cypress App, select `E2E Testing` and `Chrome` as Browser + - npm run `npm run cypress:run` + - in Cypress App, select `E2E Testing` and `Chrome` as Browser - in case of failing Tests: - - stop and restart local Server - - stop and restart local Client - - re-run Cypress Tests + - stop and restart local Server + - stop and restart local Client + - re-run Cypress Tests diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts index b188ef99ec..47f5248cf0 100644 --- a/frontend/cypress.config.ts +++ b/frontend/cypress.config.ts @@ -6,9 +6,9 @@ export default defineConfig({ experimentalMemoryManagement: true, testIsolation: true, viewportWidth: 1920, - viewportHeight: 1080, + viewportHeight: 1080 }, env: { - login_url: 'http://localhost:8544', - }, + login_url: 'http://localhost:8544' + } }); diff --git a/frontend/cypress/e2e/check-in.cy.ts b/frontend/cypress/e2e/check-in.cy.ts index f1ff021f7c..a725b088da 100644 --- a/frontend/cypress/e2e/check-in.cy.ts +++ b/frontend/cypress/e2e/check-in.cy.ts @@ -160,14 +160,18 @@ describe('OKR Check-in e2e tests', () => { keyresultDetailPage.showAllCheckins(); cy.contains('Check-in History'); cy.contains('Wert: 30 CHF'); - CheckInHistoryDialog.do().editLatestCheckIn(); + CheckInHistoryDialog.do() + .editLatestCheckIn(); cy.contains('Here we edit a metric checkin'); cy.contains('30 CHF'); cy.contains('Confidence um Target Zone (213 CHF) zu erreichen'); cy.contains('5/10'); cy.contains('Here we are'); cy.contains('A cat would be great'); - CheckInDialog.do().fillMetricCheckInValue('200').fillCheckInCommentary('We bought a new sheep').submit(); + CheckInDialog.do() + .fillMetricCheckInValue('200') + .fillCheckInCommentary('We bought a new sheep') + .submit(); cy.contains('200 CHF'); cy.contains('We bought a new sheep'); }); @@ -191,7 +195,8 @@ describe('OKR Check-in e2e tests', () => { keyresultDetailPage.showAllCheckins(); cy.contains('Check-in History'); cy.contains('Wert: 30 EUR'); - CheckInHistoryDialog.do().close(); + CheckInHistoryDialog.do() + .close(); keyresultDetailPage.close(); overviewPage @@ -229,20 +234,27 @@ describe('OKR Check-in e2e tests', () => { .fillCheckInCommentary('There is a new car') .fillCheckInInitiatives('Buy now a new pool') .submit(); - keyresultDetailPage.showAllCheckins().editLatestCheckIn(); + keyresultDetailPage.showAllCheckins() + .editLatestCheckIn(); cy.contains('For editing ordinal checkin'); cy.contains('Confidence um Target Zone zu erreichen'); cy.contains('6/10'); cy.contains('There is a new car'); cy.contains('Buy now a new pool'); - CheckInDialog.do().selectOrdinalCheckInZone('stretch').fillCheckInCommentary('We bought a new dog').submit(); + CheckInDialog.do() + .selectOrdinalCheckInZone('stretch') + .fillCheckInCommentary('We bought a new dog') + .submit(); cy.contains('We bought a new dog'); cy.contains('Buy now a new pool'); cy.contains('STRETCH'); }); it(`Should display confirm dialog when creating checkin on draft objective`, () => { - overviewPage.addObjective().fillObjectiveTitle('draft objective title').selectQuarter('3').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('draft objective title') + .selectQuarter('3') + .submitDraftObjective(); overviewPage.visitNextQuarter(); overviewPage .addKeyResult(undefined, 'draft objective title') @@ -251,17 +263,21 @@ describe('OKR Check-in e2e tests', () => { .fillKeyResultDescription('This is my description') .submit(); keyresultDetailPage.visit('I am a metric keyresult for testing'); - keyresultDetailPage.elements.addCheckin().click(); - ConfirmDialog.do().checkTitle('Check-in im Draft-Status'); - ConfirmDialog.do().checkDescription( - 'Dein Objective befindet sich noch im DRAFT Status. Möchtest du das Check-in trotzdem erfassen?', - ); + keyresultDetailPage.elements.addCheckin() + .click(); + ConfirmDialog.do() + .checkTitle('Check-in im Draft-Status'); + ConfirmDialog.do() + .checkDescription('Dein Objective befindet sich noch im DRAFT Status. Möchtest du das Check-in trotzdem erfassen?'); }); it(`Should only display last value div if last checkin is present`, () => { const objectiveName = uniqueSuffix('new objective'); - overviewPage.addObjective().fillObjectiveTitle(objectiveName).selectQuarter('3').submit(); + overviewPage.addObjective() + .fillObjectiveTitle(objectiveName) + .selectQuarter('3') + .submit(); overviewPage.visitNextQuarter(); overviewPage .addKeyResult(undefined, objectiveName) @@ -269,8 +285,10 @@ describe('OKR Check-in e2e tests', () => { .withMetricValues(Unit.PERCENT, '45', '60') .fillKeyResultDescription('Description') .submit(); - keyresultDetailPage.visit('I am a keyresult metric').createCheckIn(); - cy.getByTestId('old-checkin-value').should('not.exist'); + keyresultDetailPage.visit('I am a keyresult metric') + .createCheckIn(); + cy.getByTestId('old-checkin-value') + .should('not.exist'); CheckInDialog.do() .fillMetricCheckInValue('10') .setCheckInConfidence(0) @@ -279,7 +297,9 @@ describe('OKR Check-in e2e tests', () => { .submit(); cy.contains(`Letztes Check-in (${getCurrentDate()})`); keyresultDetailPage.createCheckIn(); - cy.contains('Letzter Wert').siblings('div').contains('10%'); + cy.contains('Letzter Wert') + .siblings('div') + .contains('10%'); }); }); }); @@ -287,8 +307,8 @@ describe('OKR Check-in e2e tests', () => { function getCurrentDate() { const today = new Date(); const yyyy = today.getFullYear(); - let mm = today.getMonth() + 1; // Months start at 0! - let dd = today.getDate(); + const mm = today.getMonth() + 1; // Months start at 0! + const dd = today.getDate(); let dd_str = '' + dd; let mm_str = '' + mm; diff --git a/frontend/cypress/e2e/duplicate-objective.cy.ts b/frontend/cypress/e2e/duplicate-objective.cy.ts index 97f996078d..896c841339 100644 --- a/frontend/cypress/e2e/duplicate-objective.cy.ts +++ b/frontend/cypress/e2e/duplicate-objective.cy.ts @@ -24,9 +24,12 @@ describe('Functionality of duplicating objectives and their belonging keyResults .submit(); cy.contains(duplicatedTitle); - overviewPage.getKeyResultOfObjective(duplicatedTitle, firstKeyResultName).should('exist'); - overviewPage.getKeyResultOfObjective(duplicatedTitle, secondKeyResultName).should('exist'); - overviewPage.getKeyResultOfObjective(duplicatedTitle, thirdKeyResultName).should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, firstKeyResultName) + .should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, secondKeyResultName) + .should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, thirdKeyResultName) + .should('exist'); }); it('Should be able to duplicate a objective into this quarter, only including one keyResult', () => { @@ -35,7 +38,8 @@ describe('Functionality of duplicating objectives and their belonging keyResults overviewPage .duplicateObjective('Build a company culture that kills the competition.') .fillObjectiveTitle(duplicatedTitle) - .excludeKeyResults([secondKeyResultName, thirdKeyResultName]) + .excludeKeyResults([secondKeyResultName, + thirdKeyResultName]) .submit(); overviewPage.getKeyResultOfObjective(duplicatedTitle, firstKeyResultName); @@ -49,13 +53,15 @@ describe('Functionality of duplicating objectives and their belonging keyResults it('Should not show option to select keyResults when objective with no keyResults is being duplicated', () => { const duplicatedTitle = 'This is a duplicated objective without any keyResults'; - overviewPage.duplicateObjective( - 'should not appear on staging, no sea takimata sanctus est Lorem ipsum dolor sit amet.', - ); - cy.contains('Key Results:').should('not.exist'); - ObjectiveDialog.do().fillObjectiveTitle(duplicatedTitle).submit(); + overviewPage.duplicateObjective('should not appear on staging, no sea takimata sanctus est Lorem ipsum dolor sit amet.'); + cy.contains('Key Results:') + .should('not.exist'); + ObjectiveDialog.do() + .fillObjectiveTitle(duplicatedTitle) + .submit(); - overviewPage.getObjectiveByName(duplicatedTitle).should('exist'); + overviewPage.getObjectiveByName(duplicatedTitle) + .should('exist'); }); it('Should be able to duplicate a objective into the next quarter, including all keyResults', () => { @@ -70,9 +76,12 @@ describe('Functionality of duplicating objectives and their belonging keyResults overviewPage.visitNextQuarter(); cy.contains(duplicatedTitle); - overviewPage.getKeyResultOfObjective(duplicatedTitle, firstKeyResultName).should('exist'); - overviewPage.getKeyResultOfObjective(duplicatedTitle, secondKeyResultName).should('exist'); - overviewPage.getKeyResultOfObjective(duplicatedTitle, thirdKeyResultName).should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, firstKeyResultName) + .should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, secondKeyResultName) + .should('exist'); + overviewPage.getKeyResultOfObjective(duplicatedTitle, thirdKeyResultName) + .should('exist'); }); it('Should not duplicate objective when cancel button is clicked', () => { @@ -84,12 +93,13 @@ describe('Functionality of duplicating objectives and their belonging keyResults .fillObjectiveDescription('Wow this is a very nice description!') .cancel(); - cy.contains(duplicatedTitle).should('not.exist'); + cy.contains(duplicatedTitle) + .should('not.exist'); }); }); describe('Verify functionality of scoring adjustment on duplicated objectives', () => { - let keyresultDetailPage = new KeyResultDetailPage(); + const keyresultDetailPage = new KeyResultDetailPage(); it('Duplicate ordinal checkin and validate value of scoring component', () => { overviewPage @@ -108,7 +118,8 @@ describe('Verify functionality of scoring adjustment on duplicated objectives', .fillCheckInInitiatives('Testmassnahmen') .submit(); - cy.intercept('GET', '**/overview?*').as('indexPage'); + cy.intercept('GET', '**/overview?*') + .as('indexPage'); keyresultDetailPage.close(); cy.wait('@indexPage'); @@ -128,11 +139,12 @@ describe('Verify functionality of scoring adjustment on duplicated objectives', .findByTestId('fail') .as('fail-area'); - cy.get('@fail-area').should(($fail) => { - expect($fail).not.to.have.css('score-red'); - expect($fail).not.to.have.css('score-yellow'); - expect($fail).not.to.have.css('score-green'); - expect($fail).not.to.have.css('score-stretch'); - }); + cy.get('@fail-area') + .should(($fail) => { + expect($fail).not.to.have.css('score-red'); + expect($fail).not.to.have.css('score-yellow'); + expect($fail).not.to.have.css('score-green'); + expect($fail).not.to.have.css('score-stretch'); + }); }); }); diff --git a/frontend/cypress/e2e/key-result.cy.ts b/frontend/cypress/e2e/key-result.cy.ts index 5a2597cf54..45d45af130 100644 --- a/frontend/cypress/e2e/key-result.cy.ts +++ b/frontend/cypress/e2e/key-result.cy.ts @@ -76,7 +76,8 @@ describe('OKR Overview', () => { .fillKeyResultDescription('This is my description when creating and then open a new') .saveAndNew(); cy.contains('Jaya Norris'); - KeyResultDialog.do().checkForDialogTextMetric(); + KeyResultDialog.do() + .checkForDialogTextMetric(); }); it('Create and edit KeyResult with Action Plan', () => { @@ -103,7 +104,8 @@ describe('OKR Overview', () => { cy.contains('A new company'); keyResultDetailPage.editKeyResult(); - cy.getByTestId('actionInput').should('have.length', 3); + cy.getByTestId('actionInput') + .should('have.length', 3); }); it('Edit a KeyResult without type change', () => { @@ -114,16 +116,24 @@ describe('OKR Overview', () => { .checkForDialogTextOrdinal() .fillKeyResultDescription('This is my description') .submit(); - keyResultDetailPage.visit('We want not to change keyresult title').editKeyResult(); + keyResultDetailPage.visit('We want not to change keyresult title') + .editKeyResult(); - cy.getByTestId('submit').should('not.be.disabled'); + cy.getByTestId('submit') + .should('not.be.disabled'); cy.contains('Key Result bearbeiten'); - cy.getByTestId('titleInput').should('have.value', 'We want not to change keyresult title'); - cy.getByTestId('commitZone').should('have.value', 'My commit zone'); - cy.getByTestId('targetZone').should('have.value', 'My target zone'); - cy.getByTestId('stretchZone').should('have.value', 'My stretch goal'); - cy.getByTestId('ownerInput').should('have.value', 'Jaya Norris'); - cy.getByTestId('descriptionInput').should('have.value', 'This is my description'); + cy.getByTestId('titleInput') + .should('have.value', 'We want not to change keyresult title'); + cy.getByTestId('commitZone') + .should('have.value', 'My commit zone'); + cy.getByTestId('targetZone') + .should('have.value', 'My target zone'); + cy.getByTestId('stretchZone') + .should('have.value', 'My stretch goal'); + cy.getByTestId('ownerInput') + .should('have.value', 'Jaya Norris'); + cy.getByTestId('descriptionInput') + .should('have.value', 'This is my description'); KeyResultDialog.do() .fillKeyResultTitle('This is the new title') @@ -149,16 +159,24 @@ describe('OKR Overview', () => { .addActionPlanElement('Action 1') .addActionPlanElement('Action 2') .submit(); - keyResultDetailPage.visit('Here we want to change keyresult title').editKeyResult(); + keyResultDetailPage.visit('Here we want to change keyresult title') + .editKeyResult(); - cy.getByTestId('submit').should('not.be.disabled'); + cy.getByTestId('submit') + .should('not.be.disabled'); cy.contains('Key Result bearbeiten'); - cy.getByTestId('titleInput').should('have.value', 'Here we want to change keyresult title'); - cy.getByTestId('commitZone').should('have.value', 'My commit zone'); - cy.getByTestId('targetZone').should('have.value', 'My target zone'); - cy.getByTestId('stretchZone').should('have.value', 'My stretch goal'); - cy.getByTestId('ownerInput').should('have.value', 'Jaya Norris'); - cy.getByTestId('descriptionInput').should('have.value', 'This is my description'); + cy.getByTestId('titleInput') + .should('have.value', 'Here we want to change keyresult title'); + cy.getByTestId('commitZone') + .should('have.value', 'My commit zone'); + cy.getByTestId('targetZone') + .should('have.value', 'My target zone'); + cy.getByTestId('stretchZone') + .should('have.value', 'My stretch goal'); + cy.getByTestId('ownerInput') + .should('have.value', 'Jaya Norris'); + cy.getByTestId('descriptionInput') + .should('have.value', 'This is my description'); KeyResultDialog.do() .fillKeyResultTitle('This is my new title for the new metric keyresult') @@ -196,82 +214,126 @@ describe('OKR Overview', () => { keyResultDetailPage.close(); - keyResultDetailPage.visit('Here we want to create a checkin').editKeyResult(); + keyResultDetailPage.visit('Here we want to create a checkin') + .editKeyResult(); - cy.getByTestId('metricTab').should('have.class', 'non-active'); + cy.getByTestId('metricTab') + .should('have.class', 'non-active'); }); it('Check validation in keyresult dialog', () => { - overviewPage.addKeyResult().checkForDialogTextMetric(); - cy.getByTestId('submit').should('be.disabled'); + overviewPage.addKeyResult() + .checkForDialogTextMetric(); + cy.getByTestId('submit') + .should('be.disabled'); KeyResultDialog.do() .fillKeyResultTitle('I am a metric keyresult') .withMetricValues(Unit.PERCENT, '21', '52') .fillKeyResultDescription('This is my description'); - cy.getByTestId('submit').should('not.be.disabled'); + cy.getByTestId('submit') + .should('not.be.disabled'); - cy.getByTestId('titleInput').clear(); - cy.getByTestId('submit').should('be.disabled'); + cy.getByTestId('titleInput') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Titel muss folgende Länge haben: 2-250 Zeichen'); - KeyResultDialog.do().fillKeyResultTitle('My title'); - cy.getByTestId('submit').should('not.be.disabled'); - cy.getByTestId('baseline').clear(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .fillKeyResultTitle('My title'); + cy.getByTestId('submit') + .should('not.be.disabled'); + cy.getByTestId('baseline') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Baseline muss eine Zahl sein'); - KeyResultDialog.do().withMetricValues(Unit.PERCENT, 'abc', '52'); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withMetricValues(Unit.PERCENT, 'abc', '52'); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Baseline muss eine Zahl sein'); - KeyResultDialog.do().withMetricValues(Unit.PERCENT, '45', '52'); - cy.getByTestId('submit').should('not.be.disabled'); - cy.getByTestId('stretchGoal').clear(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withMetricValues(Unit.PERCENT, '45', '52'); + cy.getByTestId('submit') + .should('not.be.disabled'); + cy.getByTestId('stretchGoal') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Stretch Goal muss eine Zahl sein'); - KeyResultDialog.do().withMetricValues(Unit.PERCENT, '45', 'abc'); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withMetricValues(Unit.PERCENT, '45', 'abc'); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Stretch Goal muss eine Zahl sein'); - KeyResultDialog.do().withMetricValues(Unit.PERCENT, '45', '83'); - cy.getByTestId('submit').should('not.be.disabled'); - cy.getByTestId('ownerInput').clear(); - cy.getByTestId('submit').should('be.disabled'); - - cy.getByTestId('ownerInput').type('abc'); - cy.getByTestId('titleInput').type('Hello'); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withMetricValues(Unit.PERCENT, '45', '83'); + cy.getByTestId('submit') + .should('not.be.disabled'); + cy.getByTestId('ownerInput') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); + + cy.getByTestId('ownerInput') + .type('abc'); + cy.getByTestId('titleInput') + .type('Hello'); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Owner muss ausgewählt sein'); - KeyResultDialog.do().fillOwner('Bob Baumeister'); - cy.getByTestId('submit').should('not.be.disabled'); - - cy.getByTestId('ordinalTab').click(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .fillOwner('Bob Baumeister'); + cy.getByTestId('submit') + .should('not.be.disabled'); - KeyResultDialog.do().withOrdinalValues('Commit', 'Target', 'Stretch'); - cy.getByTestId('submit').should('not.be.disabled'); + cy.getByTestId('ordinalTab') + .click(); + cy.getByTestId('submit') + .should('be.disabled'); - cy.getByTestId('commitZone').clear(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withOrdinalValues('Commit', 'Target', 'Stretch'); + cy.getByTestId('submit') + .should('not.be.disabled'); + + cy.getByTestId('commitZone') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Commit Zone muss folgende Länge haben: 1-400 Zeichen'); - KeyResultDialog.do().withOrdinalValues('Commit', 'Target', 'Stretch'); - cy.getByTestId('submit').should('not.be.disabled'); - cy.getByTestId('targetZone').clear(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withOrdinalValues('Commit', 'Target', 'Stretch'); + cy.getByTestId('submit') + .should('not.be.disabled'); + cy.getByTestId('targetZone') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Target Zone muss folgende Länge haben: 1-400 Zeichen'); - KeyResultDialog.do().withOrdinalValues('Commit', 'Target', 'Stretch'); - cy.getByTestId('submit').should('not.be.disabled'); - cy.getByTestId('stretchZone').clear(); - cy.getByTestId('submit').should('be.disabled'); + KeyResultDialog.do() + .withOrdinalValues('Commit', 'Target', 'Stretch'); + cy.getByTestId('submit') + .should('not.be.disabled'); + cy.getByTestId('stretchZone') + .clear(); + cy.getByTestId('submit') + .should('be.disabled'); cy.contains('Stretch Zone muss folgende Länge haben: 1-400 Zeichen'); - KeyResultDialog.do().withOrdinalValues('Commit', 'Target', 'Stretch'); - cy.getByTestId('submit').should('not.be.disabled'); + KeyResultDialog.do() + .withOrdinalValues('Commit', 'Target', 'Stretch'); + cy.getByTestId('submit') + .should('not.be.disabled'); }); it('Delete existing keyresult', () => { @@ -287,12 +349,11 @@ describe('OKR Overview', () => { .editKeyResult() .deleteKeyResult() .checkTitle('Key Result löschen') - .checkDescription( - 'Möchtest du dieses Key Result wirklich löschen? Zugehörige Check-ins werden dadurch ebenfalls gelöscht!', - ) + .checkDescription('Möchtest du dieses Key Result wirklich löschen? Zugehörige Check-ins werden dadurch ebenfalls gelöscht!') .submit(); cy.contains('Puzzle ITC'); - cy.get('A keyresult to delete').should('not.exist'); + cy.get('A keyresult to delete') + .should('not.exist'); }); }); diff --git a/frontend/cypress/e2e/login.cy.ts b/frontend/cypress/e2e/login.cy.ts index d7730d355b..2ab584f05c 100644 --- a/frontend/cypress/e2e/login.cy.ts +++ b/frontend/cypress/e2e/login.cy.ts @@ -6,26 +6,37 @@ describe('OKR Login', () => { }); it('Login and check correct name is displayed', () => { - cy.title().should('equal', 'Puzzle OKR'); - cy.getByTestId('user-name').contains(users.gl.name); + cy.title() + .should('equal', 'Puzzle OKR'); + cy.getByTestId('user-name') + .contains(users.gl.name); }); it('Login and logout', () => { - cy.title().should('equal', 'Puzzle OKR'); - cy.getByTestId('user-options').click(); - cy.getByTestId('logout').click(); + cy.title() + .should('equal', 'Puzzle OKR'); + cy.getByTestId('user-options') + .click(); + cy.getByTestId('logout') + .click(); cy.origin(Cypress.env('login_url'), () => { - cy.url().should('include', Cypress.env('login_url')); - cy.get('#kc-page-title').contains('Sign in to your account'); + cy.url() + .should('include', Cypress.env('login_url')); + cy.get('#kc-page-title') + .contains('Sign in to your account'); }); }); it('Click on the Hilfe button should open a new tab with the correct URL', () => { - cy.window().then((win) => { - cy.stub(win, 'open').as('openWindow'); - }); + cy.window() + .then((win) => { + cy.stub(win, 'open') + .as('openWindow'); + }); - cy.get('#hilfeButton').click(); - cy.get('@openWindow').should('be.calledWith', 'https://wiki.puzzle.ch/Puzzle/OKRs'); + cy.get('#hilfeButton') + .click(); + cy.get('@openWindow') + .should('be.calledWith', 'https://wiki.puzzle.ch/Puzzle/OKRs'); }); }); diff --git a/frontend/cypress/e2e/objective-backlog.cy.ts b/frontend/cypress/e2e/objective-backlog.cy.ts index b9d58ff14b..f14d53ba52 100644 --- a/frontend/cypress/e2e/objective-backlog.cy.ts +++ b/frontend/cypress/e2e/objective-backlog.cy.ts @@ -15,18 +15,22 @@ describe('OKR Objective Backlog e2e tests', () => { .addObjective() .fillObjectiveTitle('Objective in quarter backlog') .selectQuarter('Backlog') - .run(cy.contains('Speichern').should('not.exist')) + .run(cy.contains('Speichern') + .should('not.exist')) .run(cy.contains('Als Draft speichern')) .submitDraftObjective(); - cy.contains('Objective in quarter backlog').should('not.exist'); + cy.contains('Objective in quarter backlog') + .should('not.exist'); overviewPage.visitBacklogQuarter(); cy.contains('Objective in quarter backlog'); }); it(`Edit Objective and move to backlog`, () => { - overviewPage.addObjective().fillObjectiveTitle('Move to another quarter on edit').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('Move to another quarter on edit') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('Move to another quarter on edit', 'draft') @@ -34,16 +38,22 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - ObjectiveDialog.do().fillObjectiveTitle('This goes now to backlog').selectQuarter('Backlog').submit(); + ObjectiveDialog.do() + .fillObjectiveTitle('This goes now to backlog') + .selectQuarter('Backlog') + .submit(); - cy.contains('This goes now to backlog').should('not.exist'); + cy.contains('This goes now to backlog') + .should('not.exist'); overviewPage.visitBacklogQuarter(); cy.contains('This goes now to backlog'); }); it(`Edit ongoing Objective can not choose backlog in quarter select`, () => { - overviewPage.addObjective().fillObjectiveTitle('We can not move this to backlog').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('We can not move this to backlog') + .submit(); overviewPage .getObjectiveByNameAndState('We can not move this to backlog', 'ongoing') @@ -51,30 +61,45 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - cy.get('select#quarter').should('contain', 'GJ ForTests'); - cy.get('select#quarter').should('not.contain', 'Backlog'); + cy.get('select#quarter') + .should('contain', 'GJ ForTests'); + cy.get('select#quarter') + .should('not.contain', 'Backlog'); }); it(`Can release Objective to another quarter from backlog`, () => { overviewPage.visitBacklogQuarter(); - overviewPage.addObjective().fillObjectiveTitle('We can not release this').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('We can not release this') + .submitDraftObjective(); - overviewPage.getObjectiveByNameAndState('We can not release this', 'draft').findByTestId('three-dot-menu').click(); + overviewPage.getObjectiveByNameAndState('We can not release this', 'draft') + .findByTestId('three-dot-menu') + .click(); overviewPage.selectFromThreeDotMenu('Objective veröffentlichen'); cy.contains('Objective veröffentlichen'); - cy.getByTestId('title').first().as('title'); - cy.get('@title').clear(); - cy.get('@title').type('This is our first released objective'); - - cy.get('select#quarter').should('not.contain', 'Backlog'); - cy.get('select#quarter').select('GJ ForTests'); - - cy.contains('Als Draft speichern').should('not.exist'); + cy.getByTestId('title') + .first() + .as('title'); + cy.get('@title') + .clear(); + cy.get('@title') + .type('This is our first released objective'); + + cy.get('select#quarter') + .should('not.contain', 'Backlog'); + cy.get('select#quarter') + .select('GJ ForTests'); + + cy.contains('Als Draft speichern') + .should('not.exist'); cy.contains('Speichern'); - cy.getByTestId('save').click(); + cy.getByTestId('save') + .click(); - cy.contains('This is our first released objective').should('not.exist'); + cy.contains('This is our first released objective') + .should('not.exist'); overviewPage.visitGJForTests(); cy.contains('This is our first released objective'); @@ -82,7 +107,9 @@ describe('OKR Objective Backlog e2e tests', () => { it(`Can edit Objective title in backlog`, () => { overviewPage.visitBacklogQuarter(); - overviewPage.addObjective().fillObjectiveTitle('This is possible for edit').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('This is possible for edit') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('This is possible for edit', 'draft') @@ -90,14 +117,18 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - ObjectiveDialog.do().fillObjectiveTitle('My new title').submit(); + ObjectiveDialog.do() + .fillObjectiveTitle('My new title') + .submit(); overviewPage.getObjectiveByNameAndState('My new title', 'draft'); }); it(`Can edit Objective in backlog and change quarter`, () => { overviewPage.visitBacklogQuarter(); - overviewPage.addObjective().fillObjectiveTitle('This goes to other quarter later').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('This goes to other quarter later') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('This goes to other quarter later', 'draft') @@ -105,7 +136,9 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - ObjectiveDialog.do().selectQuarter('GJ ForTests').submit(); + ObjectiveDialog.do() + .selectQuarter('GJ ForTests') + .submit(); overviewPage.visitGJForTests(); overviewPage.getObjectiveByNameAndState('This goes to other quarter later', 'draft'); @@ -113,7 +146,9 @@ describe('OKR Objective Backlog e2e tests', () => { it(`Can duplicate in backlog`, () => { overviewPage.visitBacklogQuarter(); - overviewPage.addObjective().fillObjectiveTitle('Ready for duplicate in backlog').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('Ready for duplicate in backlog') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('Ready for duplicate in backlog', 'draft') @@ -121,7 +156,9 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective duplizieren'); - ObjectiveDialog.do().fillObjectiveTitle('This is a new duplication in backlog').submit(); + ObjectiveDialog.do() + .fillObjectiveTitle('This is a new duplication in backlog') + .submit(); overviewPage.getObjectiveByNameAndState('Ready for duplicate in backlog', 'draft'); overviewPage.getObjectiveByNameAndState('This is a new duplication in backlog', 'draft'); @@ -129,23 +166,33 @@ describe('OKR Objective Backlog e2e tests', () => { it('should duplicate from backlog', () => { overviewPage.visitBacklogQuarter(); - overviewPage.addObjective().fillObjectiveTitle('Ready for duplicate to another quarter').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('Ready for duplicate to another quarter') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('Ready for duplicate to another quarter', 'draft') .findByTestId('three-dot-menu') .click(); overviewPage.selectFromThreeDotMenu('Objective duplizieren'); - ObjectiveDialog.do().fillObjectiveTitle('New duplication from backlog').selectQuarter('GJ ForTests').submit(); + ObjectiveDialog.do() + .fillObjectiveTitle('New duplication from backlog') + .selectQuarter('GJ ForTests') + .submit(); - overviewPage.getObjectiveByNameAndState('Ready for duplicate to another quarter', 'draft').should('exist'); - cy.contains('New duplication from backlog').should('not.exist'); + overviewPage.getObjectiveByNameAndState('Ready for duplicate to another quarter', 'draft') + .should('exist'); + cy.contains('New duplication from backlog') + .should('not.exist'); overviewPage.visitGJForTests(); - overviewPage.getObjectiveByNameAndState('New duplication from backlog', 'draft').should('exist'); + overviewPage.getObjectiveByNameAndState('New duplication from backlog', 'draft') + .should('exist'); }); it(`Can duplicate ongoing Objective to backlog`, () => { - overviewPage.addObjective().fillObjectiveTitle('Possible to duplicate into backlog').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('Possible to duplicate into backlog') + .submit(); overviewPage .getObjectiveByNameAndState('Possible to duplicate into backlog', 'ongoing') @@ -153,7 +200,9 @@ describe('OKR Objective Backlog e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective duplizieren'); - ObjectiveDialog.do().selectQuarter('Backlog').submit(); + ObjectiveDialog.do() + .selectQuarter('Backlog') + .submit(); overviewPage.visitBacklogQuarter(); cy.contains('Possible to duplicate into backlog'); diff --git a/frontend/cypress/e2e/objective-crud.cy.ts b/frontend/cypress/e2e/objective-crud.cy.ts index 06a7545d03..c2af9c5754 100644 --- a/frontend/cypress/e2e/objective-crud.cy.ts +++ b/frontend/cypress/e2e/objective-crud.cy.ts @@ -10,13 +10,20 @@ describe('CRUD operations', () => { cy.loginAsUser(users.gl); }); - [ - ['ongoing objective title', 'save', 'ongoing-icon.svg'], - ['draft objective title', 'save-draft', 'draft-icon.svg'], - ].forEach(([objectiveTitle, buttonTestId, icon]) => { + [['ongoing objective title', + 'save', + 'ongoing-icon.svg'], + ['draft objective title', + 'save-draft', + 'draft-icon.svg']].forEach(([objectiveTitle, + buttonTestId, + icon]) => { it(`Create objective, no keyresults`, () => { - overviewPage.addObjective().fillObjectiveTitle(objectiveTitle).selectQuarter('3'); - cy.getByTestId(buttonTestId).click(); + overviewPage.addObjective() + .fillObjectiveTitle(objectiveTitle) + .selectQuarter('3'); + cy.getByTestId(buttonTestId) + .click(); overviewPage.visitNextQuarter(); overviewPage .getObjectiveByName(objectiveTitle) @@ -27,50 +34,72 @@ describe('CRUD operations', () => { it(`Create objective, should display error message`, () => { overviewPage.addObjective(); - cy.getByTestId('title').first().type('title').clear(); + cy.getByTestId('title') + .first() + .type('title') + .clear(); cy.contains('Titel muss folgende Länge haben: 2-250 Zeichen'); - cy.getByTestId('save').should('be.disabled'); - cy.getByTestId('save-draft').should('be.disabled'); - cy.getByTestId('cancel').should('not.be.disabled'); + cy.getByTestId('save') + .should('be.disabled'); + cy.getByTestId('save-draft') + .should('be.disabled'); + cy.getByTestId('cancel') + .should('not.be.disabled'); }); it(`Create objective, cancel`, () => { const objectiveTitle = 'this is a canceled objective'; - overviewPage.addObjective().selectQuarter('3').cancel(); + overviewPage.addObjective() + .selectQuarter('3') + .cancel(); overviewPage.visitNextQuarter(); - cy.contains(objectiveTitle).should('not.exist'); + cy.contains(objectiveTitle) + .should('not.exist'); }); it(`Delete existing objective`, () => { - overviewPage.getFirstObjective().findByTestId('three-dot-menu').click(); + overviewPage.getFirstObjective() + .findByTestId('three-dot-menu') + .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); ObjectiveDialog.do() .deleteObjective() .checkTitle('Objective löschen') - .checkDescription( - 'Möchtest du dieses Objective wirklich löschen? Zugehörige Key Results werden dadurch ebenfalls gelöscht!', - ) + .checkDescription('Möchtest du dieses Objective wirklich löschen? Zugehörige Key Results werden dadurch ebenfalls gelöscht!') .submit(); }); it(`Open objective aside via click`, () => { - overviewPage.getFirstObjective().find('.title').click(); - cy.url().should('include', 'objective'); + overviewPage.getFirstObjective() + .find('.title') + .click(); + cy.url() + .should('include', 'objective'); }); it(`update objective`, () => { const updatedTitle = 'This is an updated title'; - overviewPage.getFirstObjective().findByTestId('three-dot-menu').click(); + overviewPage.getFirstObjective() + .findByTestId('three-dot-menu') + .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - ObjectiveDialog.do().fillObjectiveTitle(updatedTitle).submit(); - cy.contains(updatedTitle).should('exist'); + ObjectiveDialog.do() + .fillObjectiveTitle(updatedTitle) + .submit(); + cy.contains(updatedTitle) + .should('exist'); }); it(`Duplicate objective`, () => { const duplicatedTitle = 'This is a duplicated objective'; - overviewPage.getFirstObjective().findByTestId('three-dot-menu').click(); + overviewPage.getFirstObjective() + .findByTestId('three-dot-menu') + .click(); overviewPage.selectFromThreeDotMenu('Objective duplizieren'); - ObjectiveDialog.do().fillObjectiveTitle(duplicatedTitle).submit(); - cy.contains(duplicatedTitle).should('exist'); + ObjectiveDialog.do() + .fillObjectiveTitle(duplicatedTitle) + .submit(); + cy.contains(duplicatedTitle) + .should('exist'); }); }); diff --git a/frontend/cypress/e2e/objective.cy.ts b/frontend/cypress/e2e/objective.cy.ts index ebe6a41af5..b7dec8295e 100644 --- a/frontend/cypress/e2e/objective.cy.ts +++ b/frontend/cypress/e2e/objective.cy.ts @@ -12,7 +12,9 @@ describe('OKR Objective e2e tests', () => { describe('tests via click', () => { it(`Release Objective from Draft to Ongoing`, () => { - overviewPage.addObjective().fillObjectiveTitle('A objective in state draft').submitDraftObjective(); + overviewPage.addObjective() + .fillObjectiveTitle('A objective in state draft') + .submitDraftObjective(); overviewPage .getObjectiveByNameAndState('A objective in state draft', 'draft') @@ -25,11 +27,14 @@ describe('OKR Objective e2e tests', () => { .checkDescription('Soll dieses Objective veröffentlicht werden?') .submit(); - overviewPage.getObjectiveByNameAndState('A objective in state draft', 'ongoing').should('exist'); + overviewPage.getObjectiveByNameAndState('A objective in state draft', 'ongoing') + .should('exist'); }); it(`Complete Objective with Successful`, () => { - overviewPage.addObjective().fillObjectiveTitle('We want to complete this successful').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('We want to complete this successful') + .submit(); overviewPage .getObjectiveByNameAndState('We want to complete this successful', 'ongoing') @@ -45,14 +50,18 @@ describe('OKR Objective e2e tests', () => { cy.contains('Objective abschliessen'); cy.contains('Abbrechen'); - cy.getByTestId('successful').click(); - cy.getByTestId('submit').click(); + cy.getByTestId('successful') + .click(); + cy.getByTestId('submit') + .click(); overviewPage.getObjectiveByNameAndState('We want to complete this successful', 'successful'); }); it(`Complete Objective with Not-Successful`, () => { - overviewPage.addObjective().fillObjectiveTitle('A not successful objective').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('A not successful objective') + .submit(); overviewPage .getObjectiveByNameAndState('A not successful objective', 'ongoing') @@ -67,14 +76,18 @@ describe('OKR Objective e2e tests', () => { cy.contains('Objective abschliessen'); cy.contains('Abbrechen'); - cy.getByTestId('not-successful').click(); - cy.getByTestId('submit').click(); + cy.getByTestId('not-successful') + .click(); + cy.getByTestId('submit') + .click(); overviewPage.getObjectiveByNameAndState('A not successful objective', 'not-successful'); }); it(`Reopen Successful Objective`, () => { - overviewPage.addObjective().fillObjectiveTitle('This objective will be reopened after').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('This objective will be reopened after') + .submit(); overviewPage .getObjectiveByNameAndState('This objective will be reopened after', 'ongoing') @@ -83,8 +96,10 @@ describe('OKR Objective e2e tests', () => { overviewPage.selectFromThreeDotMenu('Objective abschliessen'); - cy.getByTestId('successful').click(); - cy.getByTestId('submit').click(); + cy.getByTestId('successful') + .click(); + cy.getByTestId('submit') + .click(); cy.wait(500); @@ -100,11 +115,14 @@ describe('OKR Objective e2e tests', () => { .checkDescription('Soll dieses Objective wiedereröffnet werden?') .submit(); - overviewPage.getObjectiveByNameAndState('This objective will be reopened after', 'ongoing').should('exist'); + overviewPage.getObjectiveByNameAndState('This objective will be reopened after', 'ongoing') + .should('exist'); }); it(`Cancel Reopen Successful Objective`, () => { - overviewPage.addObjective().fillObjectiveTitle('The reopening of this objective will be canceled').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('The reopening of this objective will be canceled') + .submit(); overviewPage .getObjectiveByNameAndState('The reopening of this objective will be canceled', 'ongoing') @@ -113,8 +131,10 @@ describe('OKR Objective e2e tests', () => { overviewPage.selectFromThreeDotMenu('Objective abschliessen'); - cy.getByTestId('successful').click(); - cy.getByTestId('submit').click(); + cy.getByTestId('successful') + .click(); + cy.getByTestId('submit') + .click(); cy.wait(500); @@ -136,7 +156,9 @@ describe('OKR Objective e2e tests', () => { }); it('Cancel Ongoing objective back to draft state', () => { - overviewPage.addObjective().fillObjectiveTitle('This objective will be returned to draft state').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('This objective will be returned to draft state') + .submit(); overviewPage .getObjectiveByNameAndState('This objective will be returned to draft state', 'ongoing') @@ -177,9 +199,13 @@ describe('OKR Objective e2e tests', () => { }); it(`Search for Objective`, () => { - overviewPage.addObjective().fillObjectiveTitle('Search after this objective').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('Search after this objective') + .submit(); - overviewPage.addObjective().fillObjectiveTitle('We dont want to search for this').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('We dont want to search for this') + .submit(); cy.contains('Search after this objective'); cy.contains('We dont want to search for this'); @@ -187,35 +213,59 @@ describe('OKR Objective e2e tests', () => { cy.scrollTo(0, 0); cy.wait(500); - cy.getByTestId('objectiveSearch').first().click(); - cy.getByTestId('objectiveSearch').first().type('Search after').wait(350); + cy.getByTestId('objectiveSearch') + .first() + .click(); + cy.getByTestId('objectiveSearch') + .first() + .type('Search after') + .wait(350); cy.contains('Search after this objective'); - cy.contains('We dont want to search for this').should('not.exist'); + cy.contains('We dont want to search for this') + .should('not.exist'); - cy.getByTestId('objectiveSearch').first().as('objective-search').clear(); - cy.get('@objective-search').type('this').wait(350); + cy.getByTestId('objectiveSearch') + .first() + .as('objective-search') + .clear(); + cy.get('@objective-search') + .type('this') + .wait(350); cy.contains('Search after this objective'); cy.contains('We dont want to search for this'); - cy.get('@objective-search').clear(); - cy.get('@objective-search').type('dont want to').wait(350); + cy.get('@objective-search') + .clear(); + cy.get('@objective-search') + .type('dont want to') + .wait(350); cy.contains('We dont want to search for this'); - cy.contains('Search after this objective').should('not.exist'); - - cy.get('@objective-search').clear(); - cy.get('@objective-search').type('there is no objective').wait(350); - - cy.contains('We dont want to search for this').should('not.exist'); - cy.contains('Search after this objective').should('not.exist'); + cy.contains('Search after this objective') + .should('not.exist'); + + cy.get('@objective-search') + .clear(); + cy.get('@objective-search') + .type('there is no objective') + .wait(350); + + cy.contains('We dont want to search for this') + .should('not.exist'); + cy.contains('Search after this objective') + .should('not.exist'); }); it(`Create Objective in other quarter`, () => { - overviewPage.addObjective().fillObjectiveTitle('Objective in quarter 3').selectQuarter('3').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('Objective in quarter 3') + .selectQuarter('3') + .submit(); - cy.contains('Objective in quarter 3').should('not.exist'); + cy.contains('Objective in quarter 3') + .should('not.exist'); overviewPage.visitNextQuarter(); @@ -223,7 +273,9 @@ describe('OKR Objective e2e tests', () => { }); it(`Edit Objective and move to other quarter`, () => { - overviewPage.addObjective().fillObjectiveTitle('Move to another quarter on edit').submit(); + overviewPage.addObjective() + .fillObjectiveTitle('Move to another quarter on edit') + .submit(); overviewPage .getObjectiveByNameAndState('Move to another quarter on edit', 'ongoing') @@ -231,9 +283,12 @@ describe('OKR Objective e2e tests', () => { .click(); overviewPage.selectFromThreeDotMenu('Objective bearbeiten'); - ObjectiveDialog.do().selectQuarter('3').submit(); + ObjectiveDialog.do() + .selectQuarter('3') + .submit(); - cy.contains('Move to another quarter on edit').should('not.exist'); + cy.contains('Move to another quarter on edit') + .should('not.exist'); overviewPage.visitNextQuarter(); cy.contains('Move to another quarter on edit'); @@ -242,9 +297,14 @@ describe('OKR Objective e2e tests', () => { describe('tests via keyboard', () => { it(`Open objective aside via enter`, () => { - cy.getByTestId('objective').first().find('[tabindex]').first().focus(); + cy.getByTestId('objective') + .first() + .find('[tabindex]') + .first() + .focus(); cy.realPress('Enter'); - cy.url().should('include', 'objective'); + cy.url() + .should('include', 'objective'); }); }); }); diff --git a/frontend/cypress/e2e/overview.cy.ts b/frontend/cypress/e2e/overview.cy.ts index a1aafc86ab..770428a26e 100644 --- a/frontend/cypress/e2e/overview.cy.ts +++ b/frontend/cypress/e2e/overview.cy.ts @@ -7,21 +7,38 @@ describe('OKR Overview', () => { }); it('should have the current quarter with label Aktuell', () => { - cy.getByTestId('quarterFilter').contains('Aktuell'); + cy.getByTestId('quarterFilter') + .contains('Aktuell'); }); it('Check order of teams', () => { - FilterHelper.do().optionShouldNotBeSelected('Alle').toggleOption('Alle'); - const textsExpectedOrder = ['LoremIpsum', 'Puzzle ITC', '/BBT', 'we are cube.³']; + FilterHelper.do() + .optionShouldNotBeSelected('Alle') + .toggleOption('Alle'); + const textsExpectedOrder = [ + 'LoremIpsum', + 'Puzzle ITC', + '/BBT', + 'we are cube.³' + ]; cy.get('.team-title:contains("we are cube.³")'); - cy.get('.team-title').then((elements) => { - const texts: string[] = elements.map((_, el) => Cypress.$(el).text()).get(); - expect(texts).to.deep.equal(textsExpectedOrder); - }); + cy.get('.team-title') + .then((elements) => { + const texts: string[] = elements.map((_, el) => Cypress.$(el) + .text()) + .get(); + expect(texts).to.deep.equal(textsExpectedOrder); + }); }); it('Check font ', () => { - cy.get('.team-title').first().invoke('css', 'font-family').should('eq', 'Roboto, "sans-serif"'); - cy.get('.team-title').first().invoke('css', 'font-variation-settings').should('eq', '"wght" 600'); + cy.get('.team-title') + .first() + .invoke('css', 'font-family') + .should('eq', 'Roboto, "sans-serif"'); + cy.get('.team-title') + .first() + .invoke('css', 'font-variation-settings') + .should('eq', '"wght" 600'); }); }); diff --git a/frontend/cypress/e2e/routing.cy.ts b/frontend/cypress/e2e/routing.cy.ts index 58f80ef982..e08fb94367 100644 --- a/frontend/cypress/e2e/routing.cy.ts +++ b/frontend/cypress/e2e/routing.cy.ts @@ -10,24 +10,32 @@ describe('Routing', () => { describe('Route via url', () => { it('should route to overview', () => { // Visit autocalls the validatePage method - CyOverviewPage.do().visitViaURL(); + CyOverviewPage.do() + .visitViaURL(); }); it('should route to teammanagement', () => { // Visit autocalls the validatePage method - TeammanagementPage.do().visitViaURL(); + TeammanagementPage.do() + .visitViaURL(); }); it('should route from overview to team management ', () => { - CyOverviewPage.do().visitViaURL().visitTeammanagement(); + CyOverviewPage.do() + .visitViaURL() + .visitTeammanagement(); }); it('should route from team management to Overview via back button', () => { - TeammanagementPage.do().visitViaURL().backToOverview(); + TeammanagementPage.do() + .visitViaURL() + .backToOverview(); }); it('should route from team management to Overview via logo', () => { - TeammanagementPage.do().visitViaURL().visitOverview(); + TeammanagementPage.do() + .visitViaURL() + .visitOverview(); }); }); }); diff --git a/frontend/cypress/e2e/scoring.cy.ts b/frontend/cypress/e2e/scoring.cy.ts index e86da67685..4c7e421b78 100644 --- a/frontend/cypress/e2e/scoring.cy.ts +++ b/frontend/cypress/e2e/scoring.cy.ts @@ -15,13 +15,25 @@ describe('Scoring component e2e tests', () => { }); [ - [0, 100, 10], - [0, 100, 31], - [0, 100, 71], - [0, 100, 100], - ].forEach(([baseline, stretchgoal, value]) => { + [0, + 100, + 10], + [0, + 100, + 31], + [0, + 100, + 71], + [0, + 100, + 100] + ].forEach(([baseline, + stretchgoal, + value]) => { it('Create metric checkin and validate value of scoring component', () => { - setupMetricKR(`Metric kr with check-in value ${value}`, baseline, stretchgoal, value); + setupMetricKR( + `Metric kr with check-in value ${value}`, baseline, stretchgoal, value + ); const percentage = getPercentageMetric(baseline, stretchgoal, value); cy.validateScoring(false, percentage); cy.get('.keyResult-detail-attribute-show') @@ -40,12 +52,18 @@ describe('Scoring component e2e tests', () => { }); }); - [ - [0, 100, -1], - [200, 100, 250], - ].forEach(([baseline, stretchgoal, value]) => { + [[0, + 100, + -1], + [200, + 100, + 250]].forEach(([baseline, + stretchgoal, + value]) => { it('show indicator that value is negative', () => { - setupMetricKR(`Check indicator with value ${value}`, baseline, stretchgoal, value); + setupMetricKR( + `Check indicator with value ${value}`, baseline, stretchgoal, value + ); cy.validateScoring(false, 0); cy.get('.keyResult-detail-attribute-show') .contains('Aktuell') @@ -57,11 +75,17 @@ describe('Scoring component e2e tests', () => { keyresultDetailPage.close(); cy.validateScoring(true, 0); - overviewPage.getKeyResultByName(`Check indicator with value ${value}`).get('.scoring-error-badge'); + overviewPage.getKeyResultByName(`Check indicator with value ${value}`) + .get('.scoring-error-badge'); }); }); - [['fail'], ['commit'], ['target'], ['stretch']].forEach(([zoneName]) => { + [ + ['fail'], + ['commit'], + ['target'], + ['stretch'] + ].forEach(([zoneName]) => { it('Create ordinal checkin and validate value of scoring component', () => { overviewPage .addKeyResult() @@ -87,7 +111,9 @@ describe('Scoring component e2e tests', () => { }); }); -function setupMetricKR(name: string, baseline: number, stretchgoal: number, value: number) { +function setupMetricKR( + name: string, baseline: number, stretchgoal: number, value: number +) { CyOverviewPage.do() .addKeyResult() .fillKeyResultTitle(name) diff --git a/frontend/cypress/e2e/tab.cy.ts b/frontend/cypress/e2e/tab.cy.ts index 3a6a685159..ad08374842 100644 --- a/frontend/cypress/e2e/tab.cy.ts +++ b/frontend/cypress/e2e/tab.cy.ts @@ -8,18 +8,22 @@ describe('Tab workflow tests', () => { beforeEach(() => { cy.loginAsUser(users.gl); overviewPage = new CyOverviewPage(); - overviewPage.elements.logo().parent().focus(); + overviewPage.elements.logo() + .parent() + .focus(); }); function focusedShouldHaveTestId(testId: string) { - cy.focused().should('have.attr', 'data-testId', testId); + cy.focused() + .should('have.attr', 'data-testId', testId); } function tabAndCheck(testId: string, text?: string) { cy.tabForwardUntil(`[data-testId="${testId}"]`); focusedShouldHaveTestId(testId); if (text) { - cy.focused().contains(text); + cy.focused() + .contains(text); } } @@ -40,7 +44,8 @@ describe('Tab workflow tests', () => { .should('have.attr', 'src') .and('match', /search-icon.svg/); cy.tabForward(); - cy.focused().contains('Alle'); + cy.focused() + .contains('Alle'); }); it('should be able to tab to overview items', () => { @@ -68,7 +73,8 @@ describe('Tab workflow tests', () => { }); it('should focus three dot menu after edit objective', () => { - overviewPage.getObjectiveByState('ongoing').focus(); + overviewPage.getObjectiveByState('ongoing') + .focus(); tabAndCheck('three-dot-menu'); cy.realPress('Enter'); tabToThreeDotMenuOption('Objective bearbeiten'); @@ -85,17 +91,20 @@ describe('Tab workflow tests', () => { }); it('should be able to complete and reopen objective', () => { - overviewPage.getObjectiveByState('ongoing').focus(); + overviewPage.getObjectiveByState('ongoing') + .focus(); tabAndCheck('three-dot-menu'); cy.realPress('Enter'); tabToThreeDotMenuOption('Objective abschliessen'); cy.contains('h2', 'Objective abschliessen '); focusedShouldHaveTestId('close-dialog'); cy.tabForward(); - cy.focused().contains('Objective erreicht'); + cy.focused() + .contains('Objective erreicht'); cy.realPress('Enter'); cy.tabForward(); - cy.focused().contains('Objective nicht erreicht'); + cy.focused() + .contains('Objective nicht erreicht'); tabAndCheck('completeComment'); tabAndCheck('cancel', 'Abbrechen'); tabAndCheck('submit', 'Objective abschliessen'); @@ -115,7 +124,8 @@ describe('Tab workflow tests', () => { }); it('should be able to set objective to draft and publish it', () => { - overviewPage.getObjectiveByState('ongoing').focus(); + overviewPage.getObjectiveByState('ongoing') + .focus(); tabAndCheck('three-dot-menu'); cy.realPress('Enter'); tabToThreeDotMenuOption('Objective als Draft speichern'); @@ -140,8 +150,10 @@ describe('Tab workflow tests', () => { }); it('should be able to open objective detail view', () => { - overviewPage.getObjectiveByState('ongoing').focus(); - cy.realPress('Enter').tabForward(); + overviewPage.getObjectiveByState('ongoing') + .focus(); + cy.realPress('Enter') + .tabForward(); focusedShouldHaveTestId('closeDrawer'); tabAndCheck('add-keyResult-objective-detail', 'Key Result hinzufügen'); tabAndCheck('edit-objective', 'Objective bearbeiten'); @@ -154,7 +166,8 @@ describe('Tab workflow tests', () => { cy.realPress('Enter'); focusedShouldHaveTestId('close-dialog'); tabAndCheck('titleInput'); - cy.focused().type('Title'); + cy.focused() + .type('Title'); tabAndCheck('unit'); tabAndCheck('baseline'); tabAndCheck('stretchGoal'); @@ -165,19 +178,26 @@ describe('Tab workflow tests', () => { tabAndCheck('ordinalTab', 'Ordinal'); cy.realPress('Enter'); tabAndCheck('commitZone'); - cy.focused().type('Commit'); + cy.focused() + .type('Commit'); tabAndCheck('targetZone'); - cy.focused().type('Target'); + cy.focused() + .type('Target'); tabAndCheck('stretchZone'); - cy.focused().type('Stretch'); + cy.focused() + .type('Stretch'); tabAndCheck('submit', 'Speichern'); tabAndCheck('saveAndNew', 'Speichern & Neu'); tabAndCheck('cancel', 'Abbrechen'); }); it('Should tab keyresult detail view', () => { - overviewPage.getObjectiveByState('ongoing').findByTestId('key-result').first().focus(); - cy.realPress('Enter').tabForward(); + overviewPage.getObjectiveByState('ongoing') + .findByTestId('key-result') + .first() + .focus(); + cy.realPress('Enter') + .tabForward(); focusedShouldHaveTestId('close-drawer'); tabAndCheck('show-all-checkins', 'Alle Check-ins anzeigen'); cy.realPress('Enter'); @@ -196,14 +216,16 @@ describe('Tab workflow tests', () => { .fillKeyResultTitle('A metric Keyresult for tabbing tests') .withMetricValues(Unit.CHF, '10', '100') .submit(); - KeyResultDetailPage.do().visit('A metric Keyresult for tabbing tests'); + KeyResultDetailPage.do() + .visit('A metric Keyresult for tabbing tests'); tabAndCheck('add-check-in', 'Check-in erfassen'); cy.realPress('Enter'); cy.contains('Check-in erfassen'); focusedShouldHaveTestId('close-dialog'); tabAndCheck('changeInfo'); tabAndCheck('check-in-metric-value'); - cy.focused().type('20'); + cy.focused() + .type('20'); tabAndCheck('initiatives'); cy.contains('5/10'); cy.tabForward(); @@ -219,20 +241,29 @@ describe('Tab workflow tests', () => { .fillKeyResultTitle('A ordinal Keyresult for tabbing tests') .withOrdinalValues('Commit', 'Target', 'Stretch') .submit(); - KeyResultDetailPage.do().visit('A ordinal Keyresult for tabbing tests'); + KeyResultDetailPage.do() + .visit('A ordinal Keyresult for tabbing tests'); tabAndCheck('add-check-in', 'Check-in erfassen'); cy.realPress('Enter'); cy.contains('Check-in erfassen'); focusedShouldHaveTestId('close-dialog'); tabAndCheck('changeInfo'); cy.tabForward(); - cy.focused().closest('mat-radio-button').should('have.attr', 'data-testId', 'fail-radio'); + cy.focused() + .closest('mat-radio-button') + .should('have.attr', 'data-testId', 'fail-radio'); cy.realPress('ArrowDown'); - cy.focused().closest('mat-radio-button').should('have.attr', 'data-testId', 'commit-radio'); + cy.focused() + .closest('mat-radio-button') + .should('have.attr', 'data-testId', 'commit-radio'); cy.realPress('ArrowDown'); - cy.focused().closest('mat-radio-button').should('have.attr', 'data-testId', 'target-radio'); + cy.focused() + .closest('mat-radio-button') + .should('have.attr', 'data-testId', 'target-radio'); cy.realPress('ArrowDown'); - cy.focused().closest('mat-radio-button').should('have.attr', 'data-testId', 'stretch-radio'); + cy.focused() + .closest('mat-radio-button') + .should('have.attr', 'data-testId', 'stretch-radio'); tabAndCheck('initiatives'); cy.contains('5/10'); cy.tabForward(); @@ -254,18 +285,21 @@ describe('Tab workflow tests', () => { tabAndCheck('invite-member', 'Member registrieren'); }); it('Should tab create team', () => { - cy.getByTestId('team-management').click(); + cy.getByTestId('team-management') + .click(); tabAndCheck('add-team'); cy.realPress('Enter'); cy.contains('Team erfassen'); focusedShouldHaveTestId('close-dialog'); tabAndCheck('add-team-name'); - cy.focused().type('Name of new team'); + cy.focused() + .type('Name of new team'); tabAndCheck('save', 'Speichern'); tabAndCheck('cancel', 'Abbrechen'); }); it('Should tab register member', () => { - cy.getByTestId('team-management').click(); + cy.getByTestId('team-management') + .click(); tabAndCheck('invite-member'); cy.realPress('Enter'); cy.contains('Member registrieren'); @@ -274,13 +308,16 @@ describe('Tab workflow tests', () => { tabAndCheck('new-member-last-name'); tabAndCheck('email-col_0'); cy.tabForward(); - cy.focused().closest('app-puzzle-icon-button').should('have.attr', 'icon', 'delete-icon.svg'); + cy.focused() + .closest('app-puzzle-icon-button') + .should('have.attr', 'icon', 'delete-icon.svg'); tabAndCheck('new-member-add-row', 'Weiterer Member hinzufügen'); tabAndCheck('invite', 'Einladen'); tabAndCheck('new-member-cancel', 'Abbrechen'); }); it('Should tab edit member', () => { - cy.getByTestId('team-management').click(); + cy.getByTestId('team-management') + .click(); cy.pressUntilContains('Alice Wunderland', 'Tab'); cy.tabForward(); cy.realPress('Enter'); @@ -289,23 +326,31 @@ describe('Tab workflow tests', () => { // Field to toggle if user is OKR-Champion cy.tabForward(); - cy.focused().closest('app-puzzle-icon-button').should('have.attr', 'icon', 'edit.svg'); + cy.focused() + .closest('app-puzzle-icon-button') + .should('have.attr', 'icon', 'edit.svg'); cy.realPress('Enter'); cy.tabForward(); tabAndCheck('close-drawer'); cy.tabForward(); - cy.focused().closest('mat-checkbox').should('have.attr', 'data-testId', 'edit-okr-champion-checkbox'); + cy.focused() + .closest('mat-checkbox') + .should('have.attr', 'data-testId', 'edit-okr-champion-checkbox'); // Field to edit role of assigned team cy.tabForward(); - cy.focused().closest('app-puzzle-icon-button').should('have.attr', 'icon', 'edit.svg'); + cy.focused() + .closest('app-puzzle-icon-button') + .should('have.attr', 'icon', 'edit.svg'); cy.realPress('Enter'); cy.tabForward(); tabAndCheck('select-team-role', 'Team-Member'); // Button to delete assigned team cy.tabForward(); - cy.focused().closest('app-puzzle-icon-button').should('have.attr', 'icon', 'delete-icon.svg'); + cy.focused() + .closest('app-puzzle-icon-button') + .should('have.attr', 'icon', 'delete-icon.svg'); // Button to add user to another team tabAndCheck('add-user'); diff --git a/frontend/cypress/e2e/team.cy.ts b/frontend/cypress/e2e/team.cy.ts index 405eb2c993..50a88bc4a0 100644 --- a/frontend/cypress/e2e/team.cy.ts +++ b/frontend/cypress/e2e/team.cy.ts @@ -7,7 +7,8 @@ describe('OKR team e2e tests', () => { describe('tests via click', () => { beforeEach(() => { cy.loginAsUser(users.gl); - CyOverviewPage.do().visitCurrentQuarter(); + CyOverviewPage.do() + .visitCurrentQuarter(); }); it('Should select teams from teamfilter', () => { @@ -51,7 +52,8 @@ describe('OKR team e2e tests', () => { .optionShouldNotBeSelected('/BBT') .optionShouldNotBeSelected('we are cube'); - filterHelper.toggleOption('Puzzle ITC').toggleOption('LoremIpsum'); + filterHelper.toggleOption('Puzzle ITC') + .toggleOption('LoremIpsum'); cy.contains('Kein Team ausgewählt'); }); @@ -64,15 +66,23 @@ describe('OKR team e2e tests', () => { .optionShouldNotBeSelected('/BBT') .optionShouldNotBeSelected('we are cube'); - filterHelper.validateUrlParameter('teams', ['5', '6']); - - filterHelper.toggleOption('/BBT').validateUrlParameter('teams', ['4', '5', '6']); - filterHelper.toggleOption('Puzzle ITC').toggleOption('LoremIpsum').toggleOption('/BBT'); - cy.url().should('not.include', 'teams='); + filterHelper.validateUrlParameter('teams', ['5', + '6']); + + filterHelper.toggleOption('/BBT') + .validateUrlParameter('teams', ['4', + '5', + '6']); + filterHelper.toggleOption('Puzzle ITC') + .toggleOption('LoremIpsum') + .toggleOption('/BBT'); + cy.url() + .should('not.include', 'teams='); }); it('Select teams by url', () => { - cy.url().should('not.include', 'teams'); + cy.url() + .should('not.include', 'teams'); cy.visit('/?quarter=2&teams=4,5,8'); FilterHelper.do() @@ -84,16 +94,24 @@ describe('OKR team e2e tests', () => { }); it('should display less button on mobile header', () => { - let teammanagementPage = TeammanagementPage.do().visitViaURL(); - cy.intercept('POST', '**/teams').as('addTeam'); - - teammanagementPage.addTeam().fillName('X-Team').submit(); + const teammanagementPage = TeammanagementPage.do() + .visitViaURL(); + cy.intercept('POST', '**/teams') + .as('addTeam'); + + teammanagementPage.addTeam() + .fillName('X-Team') + .submit(); cy.wait('@addTeam'); cy.contains('X-Team'); - teammanagementPage.addTeam().fillName('Y-Team').submit(); + teammanagementPage.addTeam() + .fillName('Y-Team') + .submit(); cy.wait('@addTeam'); cy.contains('Y-Team'); - teammanagementPage.addTeam().fillName('Z-Team').submit(); + teammanagementPage.addTeam() + .fillName('Z-Team') + .submit(); cy.wait('@addTeam'); cy.contains('Z-Team'); @@ -102,22 +120,27 @@ describe('OKR team e2e tests', () => { // set viewport to < 768 to trigger mobile header cy.viewport(767, 1200); - cy.getByTestId('expansion-panel-header').click(); + cy.getByTestId('expansion-panel-header') + .click(); cy.contains('Weniger'); // reset viewport cy.viewport(Cypress.config('viewportWidth'), Cypress.config('viewportHeight')); cy.visit(`${teammanagementPage.getURL()}`); - cy.intercept('DELETE', '**/teams/*').as('deleteTeam'); + cy.intercept('DELETE', '**/teams/*') + .as('deleteTeam'); - teammanagementPage.deleteTeam('X-Team').submit(); + teammanagementPage.deleteTeam('X-Team') + .submit(); cy.wait('@deleteTeam'); - teammanagementPage.deleteTeam('Y-Team').submit(); + teammanagementPage.deleteTeam('Y-Team') + .submit(); cy.wait('@deleteTeam'); - teammanagementPage.deleteTeam('Z-Team').submit(); + teammanagementPage.deleteTeam('Z-Team') + .submit(); cy.wait('@deleteTeam'); }); }); diff --git a/frontend/cypress/e2e/teammanagement.cy.ts b/frontend/cypress/e2e/teammanagement.cy.ts index 5603e88143..07432f14fc 100644 --- a/frontend/cypress/e2e/teammanagement.cy.ts +++ b/frontend/cypress/e2e/teammanagement.cy.ts @@ -16,20 +16,29 @@ describe('Team management tests', () => { }); it('should preserve team filter', () => { - CyOverviewPage.do().visitViaURL(); - FilterHelper.do().toggleOption('/BBT').toggleOption('Puzzle ITC'); + CyOverviewPage.do() + .visitViaURL(); + FilterHelper.do() + .toggleOption('/BBT') + .toggleOption('Puzzle ITC'); checkTeamsSelected(); - CyOverviewPage.do().visitTeammanagement(); + CyOverviewPage.do() + .visitTeammanagement(); checkTeamsSelected(); - TeammanagementPage.do().backToOverview(); + TeammanagementPage.do() + .backToOverview(); checkTeamsSelected(); - CyOverviewPage.do().visitTeammanagement(); - TeammanagementPage.do().visitOverview(); + CyOverviewPage.do() + .visitTeammanagement(); + TeammanagementPage.do() + .visitOverview(); checkTeamsSelected(); }); function checkTeamsSelected() { - FilterHelper.do().optionShouldBeSelected('LoremIpsum').optionShouldBeSelected('/BBT'); + FilterHelper.do() + .optionShouldBeSelected('LoremIpsum') + .optionShouldBeSelected('/BBT'); } }); @@ -38,29 +47,40 @@ describe('Team management tests', () => { before(() => { // login as bl to ensure this user exists in database cy.loginAsUser(users.bl); - cy.getByTestId('user-name').click(); - cy.getByTestId('logout').click(); + cy.getByTestId('user-name') + .click(); + cy.getByTestId('logout') + .click(); }); beforeEach(() => { cy.loginAsUser(users.gl); - teammanagementPage = TeammanagementPage.do().visitViaURL(); + teammanagementPage = TeammanagementPage.do() + .visitViaURL(); }); it('Create team', () => { - cy.intercept('POST', '**/teams').as('addTeam'); + cy.intercept('POST', '**/teams') + .as('addTeam'); - teammanagementPage.addTeam().fillName(teamName).submit(); + teammanagementPage.addTeam() + .fillName(teamName) + .submit(); cy.wait('@addTeam'); cy.contains(teamName); }); it('Try to remove last admin of team should not work', () => { - cy.intercept('PUT', '**/removeuser').as('removeUser'); + cy.intercept('PUT', '**/removeuser') + .as('removeUser'); - cy.get('app-team-list .mat-mdc-list-item').contains(teamName).click(); - cy.getByTestId('member-list-more').click(); - cy.getByTestId('remove-from-member-list').click(); + cy.get('app-team-list .mat-mdc-list-item') + .contains(teamName) + .click(); + cy.getByTestId('member-list-more') + .click(); + cy.getByTestId('remove-from-member-list') + .click(); ConfirmDialog.do() .checkTitle('Mitglied entfernen') @@ -69,15 +89,21 @@ describe('Team management tests', () => { cy.wait('@removeUser'); - cy.contains('Der letzte Administrator eines Teams kann nicht entfernt werden').should('exist'); + cy.contains('Der letzte Administrator eines Teams kann nicht entfernt werden') + .should('exist'); }); it('clicking cancel in dialog when removing user should not remove user', () => { - cy.intercept('PUT', '**/removeuser').as('removeUser'); + cy.intercept('PUT', '**/removeuser') + .as('removeUser'); - cy.get('app-team-list .mat-mdc-list-item').contains(teamName).click(); - cy.getByTestId('member-list-more').click(); - cy.getByTestId('remove-from-member-list').click(); + cy.get('app-team-list .mat-mdc-list-item') + .contains(teamName) + .click(); + cy.getByTestId('member-list-more') + .click(); + cy.getByTestId('remove-from-member-list') + .click(); // cancel dialog ConfirmDialog.do() @@ -85,34 +111,46 @@ describe('Team management tests', () => { .checkDescription(`Möchtest du Jaya Norris wirklich aus dem Team '${teamName}' entfernen?`) .cancel(); - cy.get('@removeUser.all').then((interceptions) => { - expect(interceptions).to.have.length(0); - }); + cy.get('@removeUser.all') + .then((interceptions) => { + expect(interceptions).to.have.length(0); + }); }); it('Edit team', () => { - cy.intercept('GET', '**/users').as('getUsers'); - cy.intercept('GET', '**/teams').as('getTeams'); + cy.intercept('GET', '**/users') + .as('getUsers'); + cy.intercept('GET', '**/teams') + .as('getTeams'); - cy.get('app-team-list .mat-mdc-list-item').contains('LoremIpsum').click(); + cy.get('app-team-list .mat-mdc-list-item') + .contains('LoremIpsum') + .click(); editTeamNameAndTest('IpsumLorem'); cy.visit('team-management'); - cy.wait(['@getUsers', '@getTeams']); + cy.wait(['@getUsers', + '@getTeams']); - cy.contains('LoremIpsum').should('not.exist'); - cy.contains('IpsumLorem').should('exist'); + cy.contains('LoremIpsum') + .should('not.exist'); + cy.contains('IpsumLorem') + .should('exist'); // set old team name again - cy.get('app-team-list .mat-mdc-list-item').contains('IpsumLorem').click(); + cy.get('app-team-list .mat-mdc-list-item') + .contains('IpsumLorem') + .click(); editTeamNameAndTest('LoremIpsum'); }); it('Delete team', () => { - //Click delete button and cancel - teammanagementPage.deleteTeam(teamName).cancel(); + // Click delete button and cancel + teammanagementPage.deleteTeam(teamName) + .cancel(); // try again and confirm dialog - teammanagementPage.deleteTeam(teamName).submit(); + teammanagementPage.deleteTeam(teamName) + .submit(); }); describe('Search', () => { @@ -128,7 +166,9 @@ describe('Team management tests', () => { }); it('Search team', () => { - teammanagementPage.elements.teamSearch().fill('we are').selectOption('we are cube.³'); + teammanagementPage.elements.teamSearch() + .fill('we are') + .selectOption('we are cube.³'); cy.contains('app-member-list h2', 'we are cube.³'); }); @@ -148,7 +188,8 @@ describe('Team management tests', () => { describe('invite members', () => { it('invite two members', () => { - teammanagementPage.elements.registerMember().click(); + teammanagementPage.elements.registerMember() + .click(); const firstNames = InviteMembersDialog.do() .enterUser('Claudia', 'Meier', 'claudia.meier@test.ch') .addAnotherUser() @@ -158,56 +199,86 @@ describe('Team management tests', () => { // test error messages fillOutNewUser('Robin', '', 'papierer'); - cy.getByTestId('invite').click(); + cy.getByTestId('invite') + .click(); cy.contains('Angabe benötigt'); cy.contains('E-Mail ungültig'); - cy.getByTestId('email-col_2').focus(); + cy.getByTestId('email-col_2') + .focus(); cy.realType('@puzzle.ch'); - cy.contains('E-Mail ungültig').should('not.exist'); + cy.contains('E-Mail ungültig') + .should('not.exist'); cy.contains('E-Mail existiert bereits'); cy.tabBackward(); cy.realType('Papirer'); - cy.contains('Angabe benötigt').should('not.exist'); + cy.contains('Angabe benötigt') + .should('not.exist'); // delete last entry cy.tabForward(); cy.tabForward(); cy.realPress('Enter'); - cy.contains('papiererr@puzzle.ch').should('not.exist'); + cy.contains('papiererr@puzzle.ch') + .should('not.exist'); // save - cy.getByTestId('invite').click(); + cy.getByTestId('invite') + .click(); cy.contains('Die Members wurden erfolgreich registriert'); firstNames.forEach((email) => cy.contains(email)); }); }); it('Navigate to Bobs profile and add him to BBT and LoremIpsum', () => { - cy.intercept('PUT', '**/updateaddteammembership/*').as('updateEsha'); + cy.intercept('PUT', '**/updateaddteammembership/*') + .as('updateEsha'); navigateToUser(nameEsha); // add to team bbt as admin - cy.get('app-member-detail').findByTestId('add-user').click(); - cy.get('app-member-detail').findByTestId('select-team-dropdown').click(); - cy.getByTestId('select-team-dropdown-option').contains('/BBT').click(); - cy.get('app-member-detail').findByTestId('select-team-role').click(); - cy.getByTestId('select-team-role-admin').click(); - cy.get('app-member-detail').findByTestId('add-user-to-team-save').click(); + cy.get('app-member-detail') + .findByTestId('add-user') + .click(); + cy.get('app-member-detail') + .findByTestId('select-team-dropdown') + .click(); + cy.getByTestId('select-team-dropdown-option') + .contains('/BBT') + .click(); + cy.get('app-member-detail') + .findByTestId('select-team-role') + .click(); + cy.getByTestId('select-team-role-admin') + .click(); + cy.get('app-member-detail') + .findByTestId('add-user-to-team-save') + .click(); cy.wait('@updateEsha'); // add to team loremipsum as member - cy.get('app-member-detail').findByTestId('add-user').click(); - cy.get('app-member-detail').findByTestId('select-team-dropdown').click(); + cy.get('app-member-detail') + .findByTestId('add-user') + .click(); + cy.get('app-member-detail') + .findByTestId('select-team-dropdown') + .click(); // team BBT should not be in list anymore - cy.getByTestId('select-team-dropdown-option').should('not.contain', '/BBT'); + cy.getByTestId('select-team-dropdown-option') + .should('not.contain', '/BBT'); - cy.getByTestId('select-team-dropdown-option').contains('LoremIpsum').click(); - cy.get('app-member-detail').findByTestId('select-team-role').click(); - cy.getByTestId('select-team-role-member').click(); - cy.get('app-member-detail').findByTestId('add-user-to-team-save').click(); + cy.getByTestId('select-team-dropdown-option') + .contains('LoremIpsum') + .click(); + cy.get('app-member-detail') + .findByTestId('select-team-role') + .click(); + cy.getByTestId('select-team-role-member') + .click(); + cy.get('app-member-detail') + .findByTestId('add-user-to-team-save') + .click(); cy.wait('@updateEsha'); // check table @@ -218,13 +289,16 @@ describe('Team management tests', () => { let foundEsha = false; cy.get('app-member-list tbody tr') .each(($row) => { - let usernameCell = $row.find('td:nth-child(2)'); - if (usernameCell.text().trim() === nameEsha) { + const usernameCell = $row.find('td:nth-child(2)'); + if (usernameCell.text() + .trim() === nameEsha) { foundEsha = true; - let roleCell = $row.find('td:nth-child(3)'); - let teamsCell = $row.find('td:nth-child(4)'); - expect(roleCell.text().trim()).to.equal('Team-Admin, Team-Member'); - expect(teamsCell.text().trim()).to.equal('/BBT, LoremIpsum'); + const roleCell = $row.find('td:nth-child(3)'); + const teamsCell = $row.find('td:nth-child(4)'); + expect(roleCell.text() + .trim()).to.equal('Team-Admin, Team-Member'); + expect(teamsCell.text() + .trim()).to.equal('/BBT, LoremIpsum'); return false; } return true; @@ -236,39 +310,59 @@ describe('Team management tests', () => { it('Navigate to user Esha and set as okr champion', () => { navigateToUser(nameEsha); - cy.getByTestId('edit-okr-champion-readonly').contains('OKR Champion:'); - cy.getByTestId('edit-okr-champion-readonly').contains('Nein'); - cy.getByTestId('edit-okr-champion-edit').click(); - cy.getByTestId('edit-okr-champion-readonly').should('not.exist'); - cy.getByTestId('edit-okr-champion-checkbox').click(); - cy.getByTestId('edit-okr-champion-readonly').contains('OKR Champion:'); - cy.getByTestId('edit-okr-champion-readonly').contains('Ja'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('OKR Champion:'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('Nein'); + cy.getByTestId('edit-okr-champion-edit') + .click(); + cy.getByTestId('edit-okr-champion-readonly') + .should('not.exist'); + cy.getByTestId('edit-okr-champion-checkbox') + .click(); + cy.getByTestId('edit-okr-champion-readonly') + .contains('OKR Champion:'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('Ja'); cy.contains('Der Member wurde erfolgreich aktualisiert.'); // reset okr champion to false - cy.getByTestId('edit-okr-champion-edit').click(); - cy.getByTestId('edit-okr-champion-checkbox').click(); - cy.getByTestId('edit-okr-champion-readonly').contains('OKR Champion:'); - cy.getByTestId('edit-okr-champion-readonly').contains('Nein'); + cy.getByTestId('edit-okr-champion-edit') + .click(); + cy.getByTestId('edit-okr-champion-checkbox') + .click(); + cy.getByTestId('edit-okr-champion-readonly') + .contains('OKR Champion:'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('Nein'); // test click outside of element - cy.getByTestId('edit-okr-champion-edit').click(); - cy.get('app-member-detail').find('h2').click(); + cy.getByTestId('edit-okr-champion-edit') + .click(); + cy.get('app-member-detail') + .find('h2') + .click(); // checkbox should hide again - cy.getByTestId('edit-okr-champion-readonly').contains('OKR Champion:'); - cy.getByTestId('edit-okr-champion-readonly').contains('Nein'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('OKR Champion:'); + cy.getByTestId('edit-okr-champion-readonly') + .contains('Nein'); }); }); describe('As BL', () => { beforeEach(() => { cy.loginAsUser(users.bl); - cy.getByTestId('team-management').click(); - cy.intercept('GET', '**/users/*').as('getEsha'); + cy.getByTestId('team-management') + .click(); + cy.intercept('GET', '**/users/*') + .as('getEsha'); }); it('should check if correct roles for BL are set', () => { - cy.get('td').contains(nameEsha).click(); + cy.get('td') + .contains(nameEsha) + .click(); cy.wait('@getEsha'); checkRolesForEsha(); @@ -276,70 +370,108 @@ describe('Team management tests', () => { }); it('should check if team loremIpsum cannot be edited', () => { - cy.get('app-team-management').contains('LoremIpsum').click(); - cy.getByTestId('teamMoreButton').should('not.exist'); - cy.getByTestId('editTeamButton').should('not.exist'); - cy.getByTestId('member-list-more').should('not.exist'); - cy.getByTestId('edit-role').should('not.exist'); + cy.get('app-team-management') + .contains('LoremIpsum') + .click(); + cy.getByTestId('teamMoreButton') + .should('not.exist'); + cy.getByTestId('editTeamButton') + .should('not.exist'); + cy.getByTestId('member-list-more') + .should('not.exist'); + cy.getByTestId('edit-role') + .should('not.exist'); }); it('should check if team /BBT can be edited and edit name', () => { - cy.get('app-team-management').contains('/BBT').click(); - cy.getByTestId('teamMoreButton').should('exist'); + cy.get('app-team-management') + .contains('/BBT') + .click(); + cy.getByTestId('teamMoreButton') + .should('exist'); editTeamNameAndTest('/BBT_edit'); // restore old name editTeamNameAndTest('/BBT'); }); it('should add members to team /BBT', () => { - cy.get('app-team-management').contains('/BBT').click(); - cy.getByTestId('add-team-member').click(); - cy.getByTestId('search-member-to-add').click(); + cy.get('app-team-management') + .contains('/BBT') + .click(); + cy.getByTestId('add-team-member') + .click(); + cy.getByTestId('search-member-to-add') + .click(); // esha should not exist (is already member of team) const matOption = '.cdk-overlay-container mat-option'; - cy.get(matOption).contains(nameEsha).should('not.exist'); + cy.get(matOption) + .contains(nameEsha) + .should('not.exist'); // add findus peterson - cy.getByTestId('search-member-to-add').as('member-search').click(); - cy.get('@member-search').type('Find'); - cy.contains(matOption, 'Findus Peterson').click(); + cy.getByTestId('search-member-to-add') + .as('member-search') + .click(); + cy.get('@member-search') + .type('Find'); + cy.contains(matOption, 'Findus Peterson') + .click(); // add robin papierer - cy.getByTestId('search-member-to-add').click(); - cy.get(matOption).contains('Findus Peterson').should('not.exist'); - cy.get(matOption).contains('Robin Papierer').click(); + cy.getByTestId('search-member-to-add') + .click(); + cy.get(matOption) + .contains('Findus Peterson') + .should('not.exist'); + cy.get(matOption) + .contains('Robin Papierer') + .click(); // check if Findus and Robin exists in table const allMemberTableTr = '#all-member-table tbody tr'; - cy.get(allMemberTableTr).eq(0).should('contain', 'Findus Peterson'); - cy.get(allMemberTableTr).eq(1).should('contain', 'Robin Papierer'); + cy.get(allMemberTableTr) + .eq(0) + .should('contain', 'Findus Peterson'); + cy.get(allMemberTableTr) + .eq(1) + .should('contain', 'Robin Papierer'); // remove robin papierer from list cy.get(allMemberTableTr + ' button') .eq(1) .click(); - cy.get(allMemberTableTr).eq(1).should('not.exist'); + cy.get(allMemberTableTr) + .eq(1) + .should('not.exist'); - cy.getByTestId('save').click(); + cy.getByTestId('save') + .click(); }); it('should change role of Findus Peterson to Team Admin', () => { - cy.get('app-team-management').contains('/BBT').click(); + cy.get('app-team-management') + .contains('/BBT') + .click(); cy.get('app-member-list tbody tr') .each(($row) => { - let usernameCell = $row.find('td:nth-child(2)'); - if (usernameCell.text().trim() !== 'Findus Peterson') { + const usernameCell = $row.find('td:nth-child(2)'); + if (usernameCell.text() + .trim() !== 'Findus Peterson') { return; } - $row.find(`[data-testId='edit-role']`).click(); + $row.find(`[data-testId='edit-role']`) + .click(); cy.wait(500); // wait for dialog to open }) .then(() => { - cy.getByTestId('select-team-role').click(); - cy.getByTestId('select-team-role-admin').click(); - cy.getByTestId('select-team-role').should('not.exist'); + cy.getByTestId('select-team-role') + .click(); + cy.getByTestId('select-team-role-admin') + .click(); + cy.getByTestId('select-team-role') + .should('not.exist'); cy.contains('Das Team wurde erfolgreich aktualisiert.'); }); }); @@ -347,28 +479,38 @@ describe('Team management tests', () => { it('should test that Findus Peterson cannot be added to further teams', () => { navigateToUser('Findus Peterson'); - // current user BL (Esha Harris) is only admin in /BBT team. - // That's why 'add-team-member' should be disabled - cy.get('app-member-detail').getByTestId('add-user').should('be.disabled'); + /* + * current user BL (Esha Harris) is only admin in /BBT team. + * That's why 'add-team-member' should be disabled + */ + cy.get('app-member-detail') + .getByTestId('add-user') + .should('be.disabled'); }); it('should remove BBT membership of findus', () => { navigateToUser('Findus Peterson'); - cy.getByTestId('delete-team-member').click(); + cy.getByTestId('delete-team-member') + .click(); ConfirmDialog.do() .checkTitle('Mitglied entfernen') .checkDescription(`Möchtest du Findus Peterson wirklich aus dem Team '/BBT' entfernen?`) .submit(); - cy.get('app-member-detail').contains('/BBT').should('not.exist'); + cy.get('app-member-detail') + .contains('/BBT') + .should('not.exist'); }); it('should remove added memberships from esha', () => { - cy.intercept('PUT', '**/removeuser').as('removeUser'); + cy.intercept('PUT', '**/removeuser') + .as('removeUser'); navigateToUser(nameEsha); - cy.getByTestId('delete-team-member').eq(0).click(); + cy.getByTestId('delete-team-member') + .eq(0) + .click(); ConfirmDialog.do() .checkTitle('Mitglied entfernen') @@ -377,47 +519,70 @@ describe('Team management tests', () => { cy.wait('@removeUser'); - cy.getByTestId('delete-team-member').eq(0).click(); + cy.getByTestId('delete-team-member') + .eq(0) + .click(); ConfirmDialog.do() .checkTitle('Mitglied entfernen') .checkDescription(`Möchtest du ${nameEsha} wirklich aus dem Team 'LoremIpsum' entfernen?`) .submit(); - cy.get('app-member-detail').should('not.contain', '/BBT').and('not.contain', 'LoremIpsum'); + cy.get('app-member-detail') + .should('not.contain', '/BBT') + .and('not.contain', 'LoremIpsum'); }); it('Navigate to user Esha and check if okr champion is not editable', () => { navigateToUser(nameEsha); - cy.getByTestId('edit-okr-champion-readonly').should('exist'); - cy.getByTestId('edit-okr-champion-edit').should('not.exist'); + cy.getByTestId('edit-okr-champion-readonly') + .should('exist'); + cy.getByTestId('edit-okr-champion-edit') + .should('not.exist'); }); }); }); function closeOverlay() { - cy.get('.cdk-overlay-backdrop').click(-50, -50, { force: true }); + cy.get('.cdk-overlay-backdrop') + .click(-50, -50, { force: true }); } function checkRolesForEsha() { - cy.get('app-member-detail tbody tr').eq(0).should('contain', '/BBT').and('contain', 'Team-Admin'); - cy.get('app-member-detail tbody tr').eq(1).should('contain', 'LoremIpsum').and('contain', 'Team-Member'); + cy.get('app-member-detail tbody tr') + .eq(0) + .should('contain', '/BBT') + .and('contain', 'Team-Admin'); + cy.get('app-member-detail tbody tr') + .eq(1) + .should('contain', 'LoremIpsum') + .and('contain', 'Team-Member'); } function editTeamNameAndTest(teamName: string) { - cy.intercept('PUT', '**/teams/*').as('saveTeam'); - cy.getByTestId('editTeamButton').click(); - cy.getByTestId('add-team-name').as('team-name').click(); - cy.get('@team-name').clear(); - cy.get('@team-name').type(teamName); - cy.getByTestId('save').click(); + cy.intercept('PUT', '**/teams/*') + .as('saveTeam'); + cy.getByTestId('editTeamButton') + .click(); + cy.getByTestId('add-team-name') + .as('team-name') + .click(); + cy.get('@team-name') + .clear(); + cy.get('@team-name') + .type(teamName); + cy.getByTestId('save') + .click(); cy.wait('@saveTeam'); cy.contains(teamName); } function navigateToUser(userName: string) { - cy.intercept('GET', '**/users/*').as('getUser'); - cy.get('td').contains(userName).click(); + cy.intercept('GET', '**/users/*') + .as('getUser'); + cy.get('td') + .contains(userName) + .click(); cy.wait('@getUser'); } diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts index ac14a493d4..44e1c93e5a 100644 --- a/frontend/cypress/support/commands.ts +++ b/frontend/cypress/support/commands.ts @@ -12,24 +12,26 @@ Cypress.Commands.add('getByTestId', (testId: string, text?: string): Chainable = const selector = `[data-testId=${testId}]`; if (text) { - return cy.get(selector).contains(text); + return cy.get(selector) + .contains(text); } else { return cy.get(selector); } }); -Cypress.Commands.add( - 'findByTestId', +Cypress.Commands.add('findByTestId', { prevSubject: true }, (subject: JQuery, testId: string, text?: string): Chainable => { const selector = `[data-testId=${testId}]`; if (text) { - return cy.wrap(subject).find(selector).contains(text); + return cy.wrap(subject) + .find(selector) + .contains(text); } else { - return cy.wrap(subject).find(selector); + return cy.wrap(subject) + .find(selector); } - }, -); + }); Cypress.Commands.add('pressUntilContains', (text: string, key: keyof typeof keyCodeDefinitions) => { pressUntilContains(text, key); @@ -40,7 +42,8 @@ Cypress.Commands.add('tabForward', () => { }); Cypress.Commands.add('tabBackward', () => { - cy.realPress(['Shift', 'Tab']); + cy.realPress(['Shift', + 'Tab']); }); Cypress.Commands.add('tabForwardUntil', (selector: string, limit?: number) => { @@ -61,33 +64,43 @@ Cypress.Commands.add('validateScoring', (isOverview: boolean, percentage: number function loginWithCredentials(username: string, password: string) { cy.visit('/'); - cy.intercept('GET', '**/users/current').as('getCurrentUser'); - cy.origin(Cypress.env('login_url'), { args: { username, password } }, ({ username, password }) => { - cy.get('input[name="username"]').type(username); - cy.get('input[name="password"]').type(password); - cy.get('button[type="submit"]').click(); + cy.intercept('GET', '**/users/current') + .as('getCurrentUser'); + cy.origin(Cypress.env('login_url'), { args: { username, + password } }, ({ username, password }) => { + cy.get('input[name="username"]') + .type(username); + cy.get('input[name="password"]') + .type(password); + cy.get('button[type="submit"]') + .click(); cy.wait('@getCurrentUser', { responseTimeout: 10000 }); }); - cy.url().then((url) => { - const currentUrl = new URL(url); - const baseURL = new URL(Cypress.config().baseUrl!); - expect(currentUrl.pathname).equal(baseURL.pathname); - }); + cy.url() + .then((url) => { + const currentUrl = new URL(url); + const baseURL = new URL(Cypress.config().baseUrl!); + expect(currentUrl.pathname) + .equal(baseURL.pathname); + }); } -const overviewIsLoaded = () => cy.get('mat-chip').should('have.length.at.least', 2); +const overviewIsLoaded = () => cy.get('mat-chip') + .should('have.length.at.least', 2); -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) +/* + * -- This is a parent command -- + * Cypress.Commands.add("login", (email, password) => { ... }) + * + * + * -- This is a child command -- + * Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) + * + * + * -- This is a dual command -- + * Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) + * + * + * -- This will overwrite an existing command -- + * Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) + */ diff --git a/frontend/cypress/support/e2e.ts b/frontend/cypress/support/e2e.ts index 31baa58435..3628b50adf 100644 --- a/frontend/cypress/support/e2e.ts +++ b/frontend/cypress/support/e2e.ts @@ -1,24 +1,26 @@ -// *********************************************************** -// This example support/e2e.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** +/* + * *********************************************************** + * This example support/e2e.ts is processed and + * loaded automatically before your test files. + * + * This is a great place to put global configuration and + * behavior that modifies Cypress. + * + * You can change the location of this file or turn off + * automatically serving support files with the + * 'supportFile' configuration option. + * + * You can read more here: + * https://on.cypress.io/configuration + * *********************************************************** + */ import './commands'; import 'cypress-real-events'; import { onlyOn } from '@cypress/skip-test'; Cypress.Keyboard.defaults({ - keystrokeDelay: 0, + keystrokeDelay: 0 }); beforeEach(() => { diff --git a/frontend/cypress/support/helper/dom-helper/angularSearchBox.ts b/frontend/cypress/support/helper/dom-helper/angularSearchBox.ts index f1966bc9ce..706f73cfb9 100644 --- a/frontend/cypress/support/helper/dom-helper/angularSearchBox.ts +++ b/frontend/cypress/support/helper/dom-helper/angularSearchBox.ts @@ -10,7 +10,8 @@ export default class AngularSearchBox extends PageObjectMapperBase { } fill(value: string) { - const input = cy.get('input').first(); + const input = cy.get('input') + .first(); input.clear(); input.type(value); return this; @@ -27,7 +28,8 @@ export default class AngularSearchBox extends PageObjectMapperBase { } selectOption(option: string) { - cy.contains('.mat-mdc-autocomplete-panel mat-option', option).click(); + cy.contains('.mat-mdc-autocomplete-panel mat-option', option) + .click(); } getPage() { @@ -39,6 +41,7 @@ export default class AngularSearchBox extends PageObjectMapperBase { } validatePage(): void { - this.getPage().should('exist'); + this.getPage() + .should('exist'); } } diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/checkInDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/checkInDialog.ts index 55ef5aab4f..576539fc8d 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/checkInDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/checkInDialog.ts @@ -15,16 +15,20 @@ export default class CheckInDialog extends Dialog { selectOrdinalCheckInZone(zone: 'fail' | 'commit' | 'target' | 'stretch') { switch (zone) { case 'fail': - cy.getByTestId('fail-radio').click(); + cy.getByTestId('fail-radio') + .click(); break; case 'commit': - cy.getByTestId('commit-radio').click(); + cy.getByTestId('commit-radio') + .click(); break; case 'target': - cy.getByTestId('target-radio').click(); + cy.getByTestId('target-radio') + .click(); break; case 'stretch': - cy.getByTestId('stretch-radio').click(); + cy.getByTestId('stretch-radio') + .click(); break; } return this; @@ -36,7 +40,9 @@ export default class CheckInDialog extends Dialog { } setCheckInConfidence(confidence: number) { - cy.getByTestId('confidence-slider').find('input').focus(); + cy.getByTestId('confidence-slider') + .find('input') + .focus(); for (let i = 0; i < 10; i++) { cy.realPress('ArrowLeft'); } @@ -74,7 +80,8 @@ export default class CheckInDialog extends Dialog { } override submit() { - cy.getByTestId('submit-check-in').click(); + cy.getByTestId('submit-check-in') + .click(); } getPage(): Chainable { diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/checkInHistoryDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/checkInHistoryDialog.ts index d984f8b7a5..4fc5053e8c 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/checkInHistoryDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/checkInHistoryDialog.ts @@ -8,11 +8,14 @@ export default class CheckInHistoryDialog extends Dialog { } override cancel() { - cy.getByTestId('closeButton').click(); + cy.getByTestId('closeButton') + .click(); } editLatestCheckIn() { - cy.getByTestId('edit-check-in').first().click(); + cy.getByTestId('edit-check-in') + .first() + .click(); return new CheckInDialog(); } @@ -21,7 +24,10 @@ export default class CheckInHistoryDialog extends Dialog { } checkForAttribute(title: string, value: string) { - cy.get('mat-dialog-container').contains(value).parent().should('contain', title); + cy.get('mat-dialog-container') + .contains(value) + .parent() + .should('contain', title); return this; } } diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/confirmDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/confirmDialog.ts index 688d4fb0eb..677ab5127d 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/confirmDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/confirmDialog.ts @@ -3,21 +3,27 @@ import Chainable = Cypress.Chainable; export default class ConfirmDialog extends Dialog { checkTitle(title: string) { - this.getPage().contains(title).should('exist'); + this.getPage() + .contains(title) + .should('exist'); return this; } checkDescription(title: string) { - this.getPage().contains(title).should('exist'); + this.getPage() + .contains(title) + .should('exist'); return this; } override submit() { - cy.getByTestId('confirm-yes').click(); + cy.getByTestId('confirm-yes') + .click(); } override cancel() { - cy.getByTestId('confirm-no').click(); + cy.getByTestId('confirm-no') + .click(); } getPage(): Chainable { diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/dialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/dialog.ts index e2d90e61a4..fd23784bb0 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/dialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/dialog.ts @@ -8,19 +8,23 @@ export default abstract class Dialog extends PageObjectMapperBase { } override validatePage() { - this.getPage().should('exist'); + this.getPage() + .should('exist'); } submit() { - cy.getByTestId('save').click(); + cy.getByTestId('save') + .click(); } cancel() { - cy.getByTestId('cancel').click(); + cy.getByTestId('cancel') + .click(); } close() { - cy.getByTestId('close-dialog').click(); + cy.getByTestId('close-dialog') + .click(); } protected fillInputByTestId(testId: string, value: string) { diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/inviteMembersDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/inviteMembersDialog.ts index f1c493bb32..01379e7966 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/inviteMembersDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/inviteMembersDialog.ts @@ -7,16 +7,21 @@ export default class InviteMembersDialog extends Dialog { override validatePage() { super.validatePage(); - this.getPage().contains('Members registrieren').should('exist'); + this.getPage() + .contains('Members registrieren') + .should('exist'); } enterUser(firstName: string, lastName: string, email: string) { firstName = uniqueSuffix(firstName); email = uniqueSuffix(email); this.firstnames.push(firstName); - const firstNameInput = cy.get('[formcontrolname="firstname"]').last(); - const lastNameInput = cy.get('[formcontrolname="lastname"]').last(); - const emailInput = cy.get('[formcontrolname="email"]').last(); + const firstNameInput = cy.get('[formcontrolname="firstname"]') + .last(); + const lastNameInput = cy.get('[formcontrolname="lastname"]') + .last(); + const emailInput = cy.get('[formcontrolname="email"]') + .last(); this.fillInput(firstNameInput, firstName); this.fillInput(lastNameInput, lastName); this.fillInput(emailInput, email); @@ -24,15 +29,18 @@ export default class InviteMembersDialog extends Dialog { } addAnotherUser() { - cy.contains('Weiterer Member hinzufügen').click(); + cy.contains('Weiterer Member hinzufügen') + .click(); return this; } + getFirstNames() { return this.firstnames; } override submit() { - cy.getByTestId('invite').click(); + cy.getByTestId('invite') + .click(); return this.firstnames; } diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/keyResultDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/keyResultDialog.ts index 3225f4859b..b724f5131a 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/keyResultDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/keyResultDialog.ts @@ -15,15 +15,18 @@ export default class KeyResultDialog extends Dialog { } withMetricValues(unit: Unit, baseline: string, stretchGoal: string) { - cy.getByTestId('metricTab').click(); - cy.getByTestId('unit').select(unit); + cy.getByTestId('metricTab') + .click(); + cy.getByTestId('unit') + .select(unit); this.fillInputByTestId('baseline', baseline); this.fillInputByTestId('stretchGoal', stretchGoal); return this; } withOrdinalValues(commitZone: string, targetZone: string, stretchGoal: string) { - cy.getByTestId('ordinalTab').click(); + cy.getByTestId('ordinalTab') + .click(); this.fillInputByTestId('commitZone', commitZone); this.fillInputByTestId('targetZone', targetZone); this.fillInputByTestId('stretchZone', stretchGoal); @@ -32,12 +35,14 @@ export default class KeyResultDialog extends Dialog { fillOwner(owner: string) { this.fillInputByTestId('ownerInput', owner); - cy.realPress('ArrowDown').realPress('Enter'); + cy.realPress('ArrowDown') + .realPress('Enter'); return this; } addActionPlanElement(action: string) { - cy.getByTestId('add-action-plan-line').click(); + cy.getByTestId('add-action-plan-line') + .click(); cy.getByTestId('actionInput') .filter((k, el) => { return (el as HTMLInputElement).value.trim() === ''; @@ -48,7 +53,8 @@ export default class KeyResultDialog extends Dialog { } deleteKeyResult() { - cy.getByTestId('delete-keyResult').click(); + cy.getByTestId('delete-keyResult') + .click(); return new ConfirmDialog(); } @@ -83,11 +89,13 @@ export default class KeyResultDialog extends Dialog { } override submit() { - cy.getByTestId('submit').click(); + cy.getByTestId('submit') + .click(); } saveAndNew() { - cy.getByTestId('saveAndNew').click(); + cy.getByTestId('saveAndNew') + .click(); } getPage(): Chainable { diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/objectiveDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/objectiveDialog.ts index d6de2ed5ea..4957e72663 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/objectiveDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/objectiveDialog.ts @@ -14,32 +14,40 @@ export default class ObjectiveDialog extends Dialog { } selectQuarter(quarter: string) { - cy.get('select#quarter').select(quarter); + cy.get('select#quarter') + .select(quarter); return this; } toggleCreateKeyResults() { - cy.getByTestId('keyResult-checkbox').find("[type='checkbox']").check(); + cy.getByTestId('keyResult-checkbox') + .find("[type='checkbox']") + .check(); return this; } deleteObjective() { - cy.getByTestId('delete').click(); + cy.getByTestId('delete') + .click(); return new ConfirmDialog(); } submitDraftObjective() { - cy.getByTestId('save-draft').click(); + cy.getByTestId('save-draft') + .click(); } excludeKeyResults(keyResults: string[]) { keyResults.forEach((keyResult) => { - cy.get('label').contains(keyResult.slice(0, 30)).click(); + cy.get('label') + .contains(keyResult.slice(0, 30)) + .click(); }); return this; } getPage(): Chainable { - return cy.get('app-objective-form').should('exist'); + return cy.get('app-objective-form') + .should('exist'); } } diff --git a/frontend/cypress/support/helper/dom-helper/dialogs/teamDialog.ts b/frontend/cypress/support/helper/dom-helper/dialogs/teamDialog.ts index c486595d2b..8b64e8243c 100644 --- a/frontend/cypress/support/helper/dom-helper/dialogs/teamDialog.ts +++ b/frontend/cypress/support/helper/dom-helper/dialogs/teamDialog.ts @@ -4,7 +4,8 @@ import Chainable = Cypress.Chainable; export default class TeamDialog extends Dialog { override validatePage() { super.validatePage(); - this.getPage().contains('Team erfassen'); + this.getPage() + .contains('Team erfassen'); } fillName(name: string) { @@ -13,7 +14,8 @@ export default class TeamDialog extends Dialog { } override submit() { - cy.getByTestId('save').click(); + cy.getByTestId('save') + .click(); } getPage(): Chainable { diff --git a/frontend/cypress/support/helper/dom-helper/filterHelper.ts b/frontend/cypress/support/helper/dom-helper/filterHelper.ts index aaeae2c944..36bb077a4a 100644 --- a/frontend/cypress/support/helper/dom-helper/filterHelper.ts +++ b/frontend/cypress/support/helper/dom-helper/filterHelper.ts @@ -5,14 +5,19 @@ export default class FilterHelper extends PageObjectMapperBase { optionShouldBeSelected(text: string, onOverview = true): this { if (onOverview) { - cy.contains('h1:visible', text).should('have.length', 1); + cy.contains('h1:visible', text) + .should('have.length', 1); } - this.getOption(text).should('have.length', 1).should('have.css', 'background-color').and('eq', 'rgb(30, 90, 150)'); + this.getOption(text) + .should('have.length', 1) + .should('have.css', 'background-color') + .and('eq', 'rgb(30, 90, 150)'); return this; } optionShouldNotBeSelected(text: string): this { - cy.contains('h1:visible', text).should('not.exist'); + cy.contains('h1:visible', text) + .should('not.exist'); this.getOption(text) .should('have.length', 1) .should('have.css', 'background-color') @@ -21,7 +26,8 @@ export default class FilterHelper extends PageObjectMapperBase { } toggleOption(text: string): this { - this.getOption(text).click(); + this.getOption(text) + .click(); return this; } diff --git a/frontend/cypress/support/helper/dom-helper/pageObjectMapperBase.ts b/frontend/cypress/support/helper/dom-helper/pageObjectMapperBase.ts index 9b98d8fe97..ac4a103a8e 100644 --- a/frontend/cypress/support/helper/dom-helper/pageObjectMapperBase.ts +++ b/frontend/cypress/support/helper/dom-helper/pageObjectMapperBase.ts @@ -10,16 +10,21 @@ export abstract class PageObjectMapperBase { } checkForToaster(content: any, type: 'success' | 'error') { - cy.get('#toast-container').find(`.toast-${type}`).contains(content).should('exist'); + cy.get('#toast-container') + .find(`.toast-${type}`) + .contains(content) + .should('exist'); return this; } validateUrlParameter(key: string, value: any[]) { - cy.url().then((url) => { - const params = new URL(url).searchParams; - const queryParamValues = params.get(key)?.split(','); - expect(queryParamValues).to.have.length(value.length); - value.forEach((v) => expect(queryParamValues).to.include(v)); - }); + cy.url() + .then((url) => { + const params = new URL(url).searchParams; + const queryParamValues = params.get(key) + ?.split(','); + expect(queryParamValues).to.have.length(value.length); + value.forEach((v) => expect(queryParamValues).to.include(v)); + }); } } diff --git a/frontend/cypress/support/helper/dom-helper/pages/keyResultDetailPage.ts b/frontend/cypress/support/helper/dom-helper/pages/keyResultDetailPage.ts index 4a06400230..93328177d2 100644 --- a/frontend/cypress/support/helper/dom-helper/pages/keyResultDetailPage.ts +++ b/frontend/cypress/support/helper/dom-helper/pages/keyResultDetailPage.ts @@ -10,12 +10,14 @@ export default class KeyResultDetailPage extends Page { closeDrawer: () => cy.getByTestId('close-drawer'), addCheckin: () => cy.getByTestId('add-check-in'), showAllCheckins: () => cy.getByTestId('show-all-checkins'), - editKeyResult: () => cy.getByTestId('edit-keyResult'), + editKeyResult: () => cy.getByTestId('edit-keyResult') }; override validatePage() { - this.elements.addCheckin().contains('Check-in erfassen'); - this.elements.editKeyResult().contains('Key Result bearbeiten'); + this.elements.addCheckin() + .contains('Check-in erfassen'); + this.elements.editKeyResult() + .contains('Key Result bearbeiten'); } override visit(keyResultName: string): this { @@ -24,31 +26,38 @@ export default class KeyResultDetailPage extends Page { } protected doVisit(keyResultName: string): this { - CyOverviewPage.do().getKeyResultByName(keyResultName).click(); + CyOverviewPage.do() + .getKeyResultByName(keyResultName) + .click(); return this; } createCheckIn() { - this.elements.addCheckin().click(); + this.elements.addCheckin() + .click(); return new CheckInDialog(); } editKeyResult() { - this.elements.editKeyResult().click(); + this.elements.editKeyResult() + .click(); return new KeyResultDialog(); } showAllCheckins() { - this.elements.showAllCheckins().click(); + this.elements.showAllCheckins() + .click(); return new CheckInHistoryDialog(); } close(): void { - this.elements.closeDrawer().click({ force: true }); + this.elements.closeDrawer() + .click({ force: true }); } visitOverview(): void { - this.elements.logo().click(); + this.elements.logo() + .click(); } getURL(): string { diff --git a/frontend/cypress/support/helper/dom-helper/pages/overviewPage.ts b/frontend/cypress/support/helper/dom-helper/pages/overviewPage.ts index 98e6251bfa..7e302c890b 100644 --- a/frontend/cypress/support/helper/dom-helper/pages/overviewPage.ts +++ b/frontend/cypress/support/helper/dom-helper/pages/overviewPage.ts @@ -7,7 +7,7 @@ import { filterByKeyResultName, getKeyResults } from '../../keyResultHelper'; export default class CyOverviewPage extends Page { elements = { logo: () => cy.getByTestId('logo'), - teammanagement: () => cy.getByTestId('team-management'), + teammanagement: () => cy.getByTestId('team-management') }; visitGJForTests() { @@ -32,52 +32,82 @@ export default class CyOverviewPage extends Page { addObjective(teamName?: string) { if (teamName) { - this.getTeamByName(teamName).find('.add-objective').first().click(); + this.getTeamByName(teamName) + .find('.add-objective') + .first() + .click(); return new ObjectiveDialog(); } - cy.getByTestId('add-objective').first().click(); + cy.getByTestId('add-objective') + .first() + .click(); return new ObjectiveDialog(); } addKeyResult(teamName?: string, objectiveName?: string) { if (teamName && objectiveName) { - this.getObjectiveByTeamAndName(teamName, objectiveName).findByTestId('add-keyResult').first().click(); + this.getObjectiveByTeamAndName(teamName, objectiveName) + .findByTestId('add-keyResult') + .first() + .click(); } else if (teamName) { - this.getTeamByName(teamName).findByTestId('add-keyResult').first().click(); + this.getTeamByName(teamName) + .findByTestId('add-keyResult') + .first() + .click(); } else if (objectiveName) { - this.getObjectiveByName(objectiveName).findByTestId('add-keyResult').first().click(); + this.getObjectiveByName(objectiveName) + .findByTestId('add-keyResult') + .first() + .click(); } else { - cy.getByTestId('add-keyResult').first().click(); + cy.getByTestId('add-keyResult') + .first() + .click(); } return new KeyResultDialog(); } addOngoingKeyResult() { - this.getObjectiveByState('ongoing').findByTestId('add-keyResult').first().click(); + this.getObjectiveByState('ongoing') + .findByTestId('add-keyResult') + .first() + .click(); return new KeyResultDialog(); } getTeamByName(teamName: string) { - return cy.contains('.team-title', teamName).parentsUntil('#overview').last(); + return cy.contains('.team-title', teamName) + .parentsUntil('#overview') + .last(); } getFirstObjective() { - return cy.get('.objective').first(); + return cy.get('.objective') + .first(); } getObjectiveByNameAndState(objectiveName: string, state: string) { - this.getObjectivesByNameAndState(objectiveName, state).last().as('objective').scrollIntoView(); + this.getObjectivesByNameAndState(objectiveName, state) + .last() + .as('objective') + .scrollIntoView(); return cy.get('@objective'); } getObjectivesByNameAndState(objectiveName: string, state: string) { - return getObjectiveColumns().filter(filterByObjectiveName(objectiveName)).filter(filterByObjectiveState(state)); + return getObjectiveColumns() + .filter(filterByObjectiveName(objectiveName)) + .filter(filterByObjectiveState(state)); } getObjectiveByName(objectiveName: string) { - this.getObjectivesByName(objectiveName).last().as('objective').scrollIntoView(); + this.getObjectivesByName(objectiveName) + .last() + .as('objective') + .scrollIntoView(); return cy.get('@objective'); } @@ -93,52 +123,73 @@ export default class CyOverviewPage extends Page { } getKeyResultOfObjective(objectiveName: string, keyResultName: string) { - return this.getAllKeyResultsOfObjective(objectiveName).filter(filterByKeyResultName(keyResultName)); + return this.getAllKeyResultsOfObjective(objectiveName) + .filter(filterByKeyResultName(keyResultName)); } getAllKeyResultsOfObjective(objectiveName: string) { - return this.getObjectiveByName(objectiveName).find('.key-result'); + return this.getObjectiveByName(objectiveName) + .find('.key-result'); } getObjectivesByName(objectiveName: string) { - return getObjectiveColumns().filter(filterByObjectiveName(objectiveName)); + return getObjectiveColumns() + .filter(filterByObjectiveName(objectiveName)); } getObjectiveByState(state: string) { - this.getObjectivesByState(state).first().as('objective').scrollIntoView(); + this.getObjectivesByState(state) + .first() + .as('objective') + .scrollIntoView(); return cy.get('@objective'); } getObjectivesByState(state: string) { - return getObjectiveColumns().filter(filterByObjectiveState(state)); + return getObjectiveColumns() + .filter(filterByObjectiveState(state)); } getKeyResultByName(keyResultName: string) { - this.getKeyResultsByName(keyResultName).last().as('keyResult').scrollIntoView(); + this.getKeyResultsByName(keyResultName) + .last() + .as('keyResult') + .scrollIntoView(); return cy.get('@keyResult'); } getKeyResultsByName(keyresultName: string) { - return getKeyResults().filter(filterByKeyResultName(keyresultName)); + return getKeyResults() + .filter(filterByKeyResultName(keyresultName)); } selectFromThreeDotMenu(optionName: string) { - cy.contains(optionName).should('exist'); - cy.get('.objective-three-dot-menu').contains(optionName).as('option').scrollIntoView(); + cy.contains(optionName) + .should('exist'); + cy.get('.objective-three-dot-menu') + .contains(optionName) + .as('option') + .scrollIntoView(); - cy.get('@option').should('have.class', 'objective-menu-option').click(); + cy.get('@option') + .should('have.class', 'objective-menu-option') + .click(); } duplicateObjective(objectiveName: string) { - cy.intercept('GET', '**/objectives/*/keyResults').as('keyResults'); - this.getObjectiveByName(objectiveName).findByTestId('three-dot-menu').click(); + cy.intercept('GET', '**/objectives/*/keyResults') + .as('keyResults'); + this.getObjectiveByName(objectiveName) + .findByTestId('three-dot-menu') + .click(); this.selectFromThreeDotMenu('Objective duplizieren'); cy.wait('@keyResults'); return new ObjectiveDialog(); } visitTeammanagement(): void { - this.elements.teammanagement().click(); + this.elements.teammanagement() + .click(); } getURL(): string { @@ -148,6 +199,7 @@ export default class CyOverviewPage extends Page { validatePage(): void {} protected doVisit(): void { - this.elements.logo().click(); + this.elements.logo() + .click(); } } diff --git a/frontend/cypress/support/helper/dom-helper/pages/page.ts b/frontend/cypress/support/helper/dom-helper/pages/page.ts index 5cc2c63ec8..9ac04fbddd 100644 --- a/frontend/cypress/support/helper/dom-helper/pages/page.ts +++ b/frontend/cypress/support/helper/dom-helper/pages/page.ts @@ -14,7 +14,8 @@ export abstract class Page extends PageObjectMapperBase { protected abstract doVisit(arg?: any): void; afterVisit(): this { - cy.url().should('include', this.getURL()); + cy.url() + .should('include', this.getURL()); this.validatePage(); return this; } diff --git a/frontend/cypress/support/helper/dom-helper/pages/teammanagementPage.ts b/frontend/cypress/support/helper/dom-helper/pages/teammanagementPage.ts index b2af165529..44af69d882 100644 --- a/frontend/cypress/support/helper/dom-helper/pages/teammanagementPage.ts +++ b/frontend/cypress/support/helper/dom-helper/pages/teammanagementPage.ts @@ -12,47 +12,60 @@ export default class TeammanagementPage extends Page { memberHeader: () => cy.get('#member-header'), registerMember: () => cy.getByTestId('invite-member'), addTeam: () => cy.getByTestId('add-team'), - teamSearch: () => AngularSearchBox.from('app-team-management-banner [data-testId="teamManagementSearch"]'), + teamSearch: () => AngularSearchBox.from('app-team-management-banner [data-testId="teamManagementSearch"]') }; override validatePage() { - this.elements.teammanagement().contains('Teamverwaltung'); - this.elements.backToOverview().contains('Zurück zur OKR Übersicht'); - this.elements.addTeam().contains('Team erfassen'); - this.elements.teamMenu().contains('Alle Teams'); - this.elements.memberHeader().contains('Alle Teams'); - this.elements.memberHeader().contains('Members:'); - this.elements.registerMember().contains('Member registrieren'); + this.elements.teammanagement() + .contains('Teamverwaltung'); + this.elements.backToOverview() + .contains('Zurück zur OKR Übersicht'); + this.elements.addTeam() + .contains('Team erfassen'); + this.elements.teamMenu() + .contains('Alle Teams'); + this.elements.memberHeader() + .contains('Alle Teams'); + this.elements.memberHeader() + .contains('Members:'); + this.elements.registerMember() + .contains('Member registrieren'); } protected doVisit(): this { - this.elements.logo().click(); + this.elements.logo() + .click(); return this; } backToOverview(): void { - this.elements.backToOverview().click(); + this.elements.backToOverview() + .click(); } visitOverview(): void { - this.elements.logo().click(); + this.elements.logo() + .click(); } addTeam(): TeamDialog { - this.elements.addTeam().click(); + this.elements.addTeam() + .click(); return new TeamDialog(); } deleteTeam(teamName: string) { - cy.get('app-team-list .mat-mdc-list-item').contains(teamName).click(); - cy.getByTestId('teamMoreButton').click(); - cy.getByTestId('teamDeleteButton').click(); + cy.get('app-team-list .mat-mdc-list-item') + .contains(teamName) + .click(); + cy.getByTestId('teamMoreButton') + .click(); + cy.getByTestId('teamDeleteButton') + .click(); return ConfirmDialog.do() .checkTitle('Team löschen') - .checkDescription( - `Möchtest du das Team '${teamName}' wirklich löschen? Zugehörige Objectives werden dadurch in allen Quartalen ebenfalls gelöscht!`, - ); + .checkDescription(`Möchtest du das Team '${teamName}' wirklich löschen? Zugehörige Objectives werden dadurch in allen Quartalen ebenfalls gelöscht!`); } getURL(): string { diff --git a/frontend/cypress/support/helper/keyResultHelper.ts b/frontend/cypress/support/helper/keyResultHelper.ts index 9f86509330..0edaa2d253 100644 --- a/frontend/cypress/support/helper/keyResultHelper.ts +++ b/frontend/cypress/support/helper/keyResultHelper.ts @@ -3,7 +3,8 @@ export function filterByKeyResultName(keyResultName: string) { } const isKeyResultName = (element: HTMLElement, keyResultName: string) => { - return Cypress.$(element).find(`:contains("${keyResultName}")`).length > 0; + return Cypress.$(element) + .find(`:contains("${keyResultName}")`).length > 0; }; export function getKeyResults() { diff --git a/frontend/cypress/support/helper/objectiveHelper.ts b/frontend/cypress/support/helper/objectiveHelper.ts index 54d633dbb3..b0bf9edae2 100644 --- a/frontend/cypress/support/helper/objectiveHelper.ts +++ b/frontend/cypress/support/helper/objectiveHelper.ts @@ -7,11 +7,13 @@ export function filterByObjectiveState(icon: string) { } const isObjectiveState = (element: HTMLElement, icon: string) => { - return Cypress.$(element).find(`[src='assets/icons/${icon}-icon.svg']`).length > 0; + return Cypress.$(element) + .find(`[src='assets/icons/${icon}-icon.svg']`).length > 0; }; const isObjectiveName = (element: HTMLElement, objectiveName: string) => { - return Cypress.$(element).find(`:contains("${objectiveName}")`).length > 0; + return Cypress.$(element) + .find(`:contains("${objectiveName}")`).length > 0; }; export function getObjectiveColumns() { diff --git a/frontend/cypress/support/helper/scoringSupport.ts b/frontend/cypress/support/helper/scoringSupport.ts index e6a92fdd13..ccb55625de 100644 --- a/frontend/cypress/support/helper/scoringSupport.ts +++ b/frontend/cypress/support/helper/scoringSupport.ts @@ -7,11 +7,13 @@ interface ScoringValue { } export function validateScoring(isOverview: boolean, percentage: number) { - let rgbCode = colorFromPercentage(percentage); - let scoringValue = scoringValueFromPercentage(percentage); + const rgbCode = colorFromPercentage(percentage); + const scoringValue = scoringValueFromPercentage(percentage); if (percentage >= 100) { - cy.getZone('stretch', isOverview).should('have.attr', 'src').should('include', 'star-filled-icon.svg'); + cy.getZone('stretch', isOverview) + .should('have.attr', 'src') + .should('include', 'star-filled-icon.svg'); } validateScoringWidth('fail', scoringValue.failPercent, isOverview); @@ -52,9 +54,13 @@ function validateScoringWidth(zone: string, percent: number, isOverview: boolean } function validateScoringColor(zone: string, rgbCode: string, isOverview: boolean) { - cy.getZone(zone, isOverview).invoke('css', 'background-color').should('equal', rgbCode); + cy.getZone(zone, isOverview) + .invoke('css', 'background-color') + .should('equal', rgbCode); if (rgbCode == 'rgba(0, 0, 0, 0)') { - cy.getByTestId('star-scoring').invoke('css', 'background-image').should('contain', 'scoring-stars'); + cy.getByTestId('star-scoring') + .invoke('css', 'background-image') + .should('contain', 'scoring-stars'); checkVisibilityOfScoringComponent(isOverview, 'block', 'star-scoring'); checkVisibilityOfScoringComponent(isOverview, 'none', 'normal-scoring'); } else { @@ -79,14 +85,22 @@ function colorFromPercentage(percentage: number) { function scoringValueFromPercentage(percentage: number): ScoringValue { if (percentage >= 100) { - return { failPercent: 0, commitPercent: 0, targetPercent: 0 }; + return { failPercent: 0, + commitPercent: 0, + targetPercent: 0 }; } else if (percentage > 70) { - let targetPercent = (percentage - 70) * (100 / 30); - return { failPercent: 100, commitPercent: 100, targetPercent: targetPercent }; + const targetPercent = (percentage - 70) * (100 / 30); + return { failPercent: 100, + commitPercent: 100, + targetPercent: targetPercent }; } else if (percentage > 30) { - let commitPercent = (percentage - 30) * (100 / 40); - return { failPercent: 100, commitPercent: commitPercent, targetPercent: -1 }; + const commitPercent = (percentage - 30) * (100 / 40); + return { failPercent: 100, + commitPercent: commitPercent, + targetPercent: -1 }; } - let failPercent = percentage * (100 / 30); - return { failPercent: failPercent, commitPercent: -1, targetPercent: -1 }; + const failPercent = percentage * (100 / 30); + return { failPercent: failPercent, + commitPercent: -1, + targetPercent: -1 }; } diff --git a/frontend/cypress/support/helper/utils.ts b/frontend/cypress/support/helper/utils.ts index 5b573b0b77..454ba2433c 100644 --- a/frontend/cypress/support/helper/utils.ts +++ b/frontend/cypress/support/helper/utils.ts @@ -10,9 +10,14 @@ export function pressUntilContains(text: string, key: keyof typeof keyCodeDefini pressUntil(key, condition); } -export function doUntilSelector(selector: string, tab: () => void, limit: number = 100, count: number = 0) { - const condition = (element: HTMLElement) => Cypress.$(element).is(selector); - doUntil(condition, tab, limit, count); +export function doUntilSelector( + selector: string, tab: () => void, limit = 100, count = 0 +) { + const condition = (element: HTMLElement) => Cypress.$(element) + .is(selector); + doUntil( + condition, tab, limit, count + ); } function pressUntil(key: keyof typeof keyCodeDefinitions, condition: (elem: HTMLElement) => boolean) { @@ -22,17 +27,20 @@ function pressUntil(key: keyof typeof keyCodeDefinitions, condition: (elem: HTML function doUntil( condition: (element: HTMLElement) => boolean, tab: () => void, - limit: number = 100, - count: number = 0, + limit = 100, + count = 0 ) { if (count >= limit) return; - cy.focused().then((element) => { - if (condition(element.get(0))) { - return; - } else { - tab(); - doUntil(condition, tab, limit, count + 1); - } - }); + cy.focused() + .then((element) => { + if (condition(element.get(0))) { + return; + } else { + tab(); + doUntil( + condition, tab, limit, count + 1 + ); + } + }); } diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 0929c9d4c0..3b2afd4e25 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -55,9 +55,9 @@ export default tsEslint.config( '@stylistic/object-curly-spacing': ['error', 'always'], '@stylistic/array-bracket-newline': ['error', { minItems: 4 }], '@stylistic/semi-style': ['error'], - "space-before-function-paren": ["error", "never"], + 'space-before-function-paren': ['error', 'never'], '@stylistic/function-paren-newline': ['error', { minItems: 4 }], - "@stylistic/space-before-function-paren": ["error", "never"], + '@stylistic/space-before-function-paren': ['error', 'never'], '@angular-eslint/directive-selector': [ 'error', diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e35687a7ae..26f879b242 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -353,6 +353,40 @@ } } }, + "node_modules/@angular-eslint/builder/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular-eslint/builder/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@angular-eslint/bundled-angular-compiler": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", @@ -458,6 +492,24 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-eslint/schematics/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@angular-eslint/schematics/node_modules/ignore": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", @@ -478,6 +530,22 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/@angular-eslint/schematics/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@angular-eslint/template-parser": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", @@ -708,6 +776,36 @@ "typescript": ">=5.4 <5.6" } }, + "node_modules/@angular/compiler-cli/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@angular/compiler-cli/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@angular/core": { "version": "18.2.13", "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.13.tgz", @@ -6597,6 +6695,24 @@ "yarn": ">= 1.13.0" } }, + "node_modules/angular-eslint/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/angular-eslint/node_modules/magic-string": { "version": "0.30.12", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", @@ -6607,6 +6723,22 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/angular-eslint/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/angular-oauth2-oidc": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-17.0.2.tgz", @@ -7604,19 +7736,41 @@ } }, "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 8.10.0" }, "funding": { "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/chownr": { @@ -15307,17 +15461,29 @@ } }, "node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">= 14.16.0" + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" }, "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/reflect-metadata": { @@ -15824,70 +15990,6 @@ } } }, - "node_modules/sass/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/sass/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/sass/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", @@ -18558,44 +18660,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/webpack-dev-server/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", @@ -18621,32 +18685,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index a45b15ce2b..d73c397344 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -24,39 +24,39 @@ const routes: Routes = [ path: '', component: OverviewComponent, resolve: { - user: currentUserResolver, + user: currentUserResolver }, - children: [ - { - path: 'details', - component: SidepanelComponent, - children: [ - { - path: 'objective/:id', - component: ObjectiveDetailComponent, - }, - { - path: 'keyresult/:id', - component: KeyresultDetailComponent, - }, - ], + children: [{ + path: 'details', + component: SidepanelComponent, + children: [{ + path: 'objective/:id', + component: ObjectiveDetailComponent }, - ], - canActivate: [authGuard], + { + path: 'keyresult/:id', + component: KeyresultDetailComponent + }] + }], + canActivate: [authGuard] }, { path: 'team-management', loadChildren: () => import('./team-management/team-management.module').then((m) => m.TeamManagementModule), canActivate: [authGuard], - resolve: { user: currentUserResolver }, + resolve: { user: currentUserResolver } }, - { path: 'objective', redirectTo: 'details/objective' }, - { path: 'keyresult', redirectTo: 'details/keyresult' }, - { path: '**', redirectTo: '', pathMatch: 'full' }, + { path: 'objective', + redirectTo: 'details/objective' }, + { path: 'keyresult', + redirectTo: 'details/keyresult' }, + { path: '**', + redirectTo: '', + pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], - exports: [RouterModule], + exports: [RouterModule] }) export class AppRoutingModule {} diff --git a/frontend/src/app/app.component.spec.ts b/frontend/src/app/app.component.spec.ts index 05f5175a80..3d1bda7afb 100644 --- a/frontend/src/app/app.component.spec.ts +++ b/frontend/src/app/app.component.spec.ts @@ -27,44 +27,46 @@ const oauthServiceMock = { loadDiscoveryDocumentAndTryLogin(): Promise { this.initCodeFlow(); return Promise.resolve(); - }, + } }; const routerMock = { root: jest.fn(), // Router - events: of(new NavigationEnd(0, 'http://localhost:4200/objective/2', 'http://localhost:4200/objective/2')), + events: of(new NavigationEnd(0, 'http://localhost:4200/objective/2', 'http://localhost:4200/objective/2')) }; -const routes: Routes = [ - { - path: '', - component: OverviewComponent, - children: [{ path: 'objective/:id', component: ObjectiveDetailComponent, pathMatch: 'full' }], - }, -]; +const routes: Routes = [{ + path: '', + component: OverviewComponent, + children: [{ path: 'objective/:id', + component: ObjectiveDetailComponent, + pathMatch: 'full' }] +}]; describe('AppComponent', () => { let component: AppComponent; let fixture: ComponentFixture; let loader: HarnessLoader; - beforeEach(async () => { + beforeEach(async() => { await TestBed.configureTestingModule({ imports: [ RouterTestingModule.withRoutes(routes), HttpClientTestingModule, TranslateTestingModule.withTranslations({ - de: de, + de: de }), OAuthModule.forRoot(), MatSidenavModule, NoopAnimationsModule, - CommonModule, + CommonModule ], - providers: [{ provide: OAuthService, useValue: oauthServiceMock }], - declarations: [AppComponent, OverviewComponent], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers: [{ provide: OAuthService, + useValue: oauthServiceMock }], + declarations: [AppComponent, + OverviewComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] }) .compileComponents() .then(() => { @@ -78,6 +80,7 @@ describe('AppComponent', () => { }); test('should create the app', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); }); diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 854233b3af..8b2861a876 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -6,21 +6,16 @@ import { DomSanitizer } from '@angular/platform-browser'; selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, + changeDetection: ChangeDetectionStrategy.OnPush }) export class AppComponent { readonly PATH_PREFIX = '../assets/icons/'; - constructor( - private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer, - ) { - this.matIconRegistry.addSvgIcon( - 'pz-search', - this.domSanitizer.bypassSecurityTrustResourceUrl(this.PATH_PREFIX + 'search-icon.svg'), - ); - this.matIconRegistry.addSvgIcon( - 'pz-menu-icon', - this.domSanitizer.bypassSecurityTrustResourceUrl(this.PATH_PREFIX + 'three-dot-menu-icon.svg'), - ); + + constructor(private matIconRegistry: MatIconRegistry, + private domSanitizer: DomSanitizer) { + this.matIconRegistry.addSvgIcon('pz-search', + this.domSanitizer.bypassSecurityTrustResourceUrl(this.PATH_PREFIX + 'search-icon.svg')); + this.matIconRegistry.addSvgIcon('pz-menu-icon', + this.domSanitizer.bypassSecurityTrustResourceUrl(this.PATH_PREFIX + 'three-dot-menu-icon.svg')); } } diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index cd2e70a8d3..053e984698 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -7,7 +7,7 @@ import { HttpBackend, HttpClient, provideHttpClient, - withInterceptorsFromDi, + withInterceptorsFromDi } from '@angular/common/http'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -71,12 +71,12 @@ import { CustomizationService } from './services/customization.service'; import { MetricCheckInDirective } from './components/checkin/check-in-form-metric/metric-check-in-directive'; function initOauthFactory(configService: ConfigService, oauthService: OAuthService) { - return async () => { + return async() => { const config = await firstValueFrom(configService.config$); oauthService.configure({ ...environment.oauth, issuer: config.issuer, - clientId: config.clientId, + clientId: config.clientId }); }; } @@ -91,14 +91,14 @@ export function storageFactory(): OAuthStorage { export const MY_FORMATS = { parse: { - dateInput: 'LL', + dateInput: 'LL' }, display: { dateInput: 'DD.MM.YYYY', monthYearLabel: 'DD.MM.YYYY', dateA11yLabel: 'DD.MM.YYYY', - monthYearA11yLabel: 'DD.MM.YYYY', - }, + monthYearA11yLabel: 'DD.MM.YYYY' + } }; @NgModule({ @@ -124,7 +124,7 @@ export const MY_FORMATS = { CheckInFormMetricComponent, CheckInFormOrdinalComponent, CheckInFormComponent, - MetricCheckInDirective, + MetricCheckInDirective ], bootstrap: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -153,8 +153,8 @@ export const MY_FORMATS = { loader: { provide: TranslateLoader, useFactory: createTranslateLoader, - deps: [HttpBackend], - }, + deps: [HttpBackend] + } }), OAuthModule.forRoot(), MatRadioModule, @@ -170,31 +170,39 @@ export const MY_FORMATS = { CdkDrag, A11yModule, CdkDragHandle, - SharedModule, + SharedModule ], providers: [ { provide: DateAdapter, useClass: MomentDateAdapter, - deps: [MAT_DATE_LOCALE], + deps: [MAT_DATE_LOCALE] }, - { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }, - { provide: HTTP_INTERCEPTORS, useClass: OauthInterceptor, multi: true }, - { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, - { provide: OAuthStorage, useFactory: storageFactory }, + { provide: MAT_DATE_FORMATS, + useValue: MY_FORMATS }, + { provide: HTTP_INTERCEPTORS, + useClass: OauthInterceptor, + multi: true }, + { provide: HTTP_INTERCEPTORS, + useClass: ErrorInterceptor, + multi: true }, + { provide: OAuthStorage, + useFactory: storageFactory }, { provide: APP_INITIALIZER, useFactory: initOauthFactory, - deps: [ConfigService, OAuthService, Injector], - multi: true, + deps: [ConfigService, + OAuthService, + Injector], + multi: true }, { provide: Router, - useClass: CustomRouter, + useClass: CustomRouter }, TranslateService, - provideHttpClient(withInterceptorsFromDi()), - ], + provideHttpClient(withInterceptorsFromDi()) + ] }) export class AppModule { constructor(private readonly customizationService: CustomizationService) {} diff --git a/frontend/src/app/components/action-plan/action-plan.component.html b/frontend/src/app/components/action-plan/action-plan.component.html index 68388cea32..364623195b 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.html +++ b/frontend/src/app/components/action-plan/action-plan.component.html @@ -9,7 +9,11 @@ (cdkDropListDropped)="drop($event)" id="actionlist" > -

+
{ @@ -24,19 +24,24 @@ describe('ActionPlanComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ActionPlanComponent], - imports: [HttpClientTestingModule, CdkDropList, CdkDrag, TranslateModule.forRoot()], + imports: [ + HttpClientTestingModule, + CdkDropList, + CdkDrag, + TranslateModule.forRoot() + ], providers: [ TranslateService, DialogService, { provide: ActionService, - useValue: actionServiceMock, + useValue: actionServiceMock }, { provide: MatDialogRef, - useValue: matDialogRef, - }, - ], + useValue: matDialogRef + } + ] }); fixture = TestBed.createComponent(ActionPlanComponent); component = fixture.componentInstance; @@ -45,11 +50,13 @@ describe('ActionPlanComponent', () => { }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); it('should remove item from actionplan array', () => { - component.control = new BehaviorSubject([action1, action2]); + component.control = new BehaviorSubject([action1, + action2]); actionServiceMock.deleteAction.mockReturnValue(of(null)); jest .spyOn(component.dialogService, 'openConfirmDialog') @@ -57,10 +64,14 @@ describe('ActionPlanComponent', () => { component.removeAction(0); - expect(actionServiceMock.deleteAction).toHaveBeenCalledWith(action1.id); - expect(component.control.getValue()).toHaveLength(1); - expect(component.control.getValue()![0]).toBe(action2); - expect(component.control.getValue()![0].priority).toBe(0); + expect(actionServiceMock.deleteAction) + .toHaveBeenCalledWith(action1.id); + expect(component.control.getValue()) + .toHaveLength(1); + expect(component.control.getValue()![0]) + .toBe(action2); + expect(component.control.getValue()![0].priority) + .toBe(0); }); it('should remove item from actionplan without opening dialog when action has no text and id', () => { @@ -69,35 +80,47 @@ describe('ActionPlanComponent', () => { component.removeAction(0); - expect(component.control.getValue()!).toHaveLength(0); - expect(dialogSpy).toHaveBeenCalledTimes(0); + expect(component.control.getValue()!) + .toHaveLength(0); + expect(dialogSpy) + .toHaveBeenCalledTimes(0); expect(actionServiceMock.deleteAction).not.toHaveBeenCalled(); }); it('should decrease index of active item when index is the same as the one of the removed item', () => { jest.spyOn(component.dialogService, 'open'); - component.control = new BehaviorSubject([action2, action3, action1]); + component.control = new BehaviorSubject([action2, + action3, + action1]); component.activeItem = 2; component.removeAction(2); - expect(component.activeItem).toBe(1); + expect(component.activeItem) + .toBe(1); }); it('should add new action with empty text into array', () => { component.control = new BehaviorSubject([]); component.keyResultId = addedAction.keyResultId; component.addNewAction(); - expect(component.control.getValue()).toHaveLength(1); - expect(component.control.getValue()![0]).toStrictEqual(addedAction); + expect(component.control.getValue()) + .toHaveLength(1); + expect(component.control.getValue()![0]) + .toStrictEqual(addedAction); }); it('should decrease index of active item', () => { const keyEvent = new KeyboardEvent('keydown', { key: 'ArrowUp' }); - component.control.next([action1, action2, action3]); + component.control.next([action1, + action2, + action3]); component.handleKeyDown(keyEvent, 2); expect((component.activeItem = 1)); - expect(component.control.getValue()!.toString()).toBe([action1, action3, action2].toString()); + expect(component.control.getValue()!.toString()) + .toBe([action1, + action3, + action2].toString()); expect(component.control.getValue()![0].priority == 0); expect(component.control.getValue()![1].priority == 1); expect(component.control.getValue()![2].priority == 2); @@ -105,11 +128,22 @@ describe('ActionPlanComponent', () => { it('should increase index of active item', () => { const keyEvent = new KeyboardEvent('keydown', { key: 'ArrowDown' }); - component.control.next([action1, action2, action3, action1]); + component.control.next([ + action1, + action2, + action3, + action1 + ]); component.handleKeyDown(keyEvent, 2); expect((component.activeItem = 3)); - expect(component.control.getValue()!.toString()).toBe([action1, action3, action1, action3].toString()); + expect(component.control.getValue()!.toString()) + .toBe([ + action1, + action3, + action1, + action3 + ].toString()); expect(component.control.getValue()![0].priority == 0); expect(component.control.getValue()![1].priority == 1); expect(component.control.getValue()![2].priority == 2); @@ -118,15 +152,21 @@ describe('ActionPlanComponent', () => { it('should increase active item index', () => { component.activeItem = 0; - component.control.next([action1, action2, action3]); + component.control.next([action1, + action2, + action3]); component.increaseActiveItemWithTab(); - expect(component.activeItem).toBe(1); + expect(component.activeItem) + .toBe(1); }); it('should decrease active item index', () => { component.activeItem = 2; - component.control.next([action1, action2, action3]); + component.control.next([action1, + action2, + action3]); component.decreaseActiveItemWithShiftTab(); - expect(component.activeItem).toBe(1); + expect(component.activeItem) + .toBe(1); }); }); diff --git a/frontend/src/app/components/action-plan/action-plan.component.ts b/frontend/src/app/components/action-plan/action-plan.component.ts index e08f5da787..623055e1d8 100644 --- a/frontend/src/app/components/action-plan/action-plan.component.ts +++ b/frontend/src/app/components/action-plan/action-plan.component.ts @@ -9,20 +9,20 @@ import { DialogService } from '../../services/dialog.service'; @Component({ selector: 'app-action-plan', templateUrl: './action-plan.component.html', - styleUrls: ['./action-plan.component.scss'], + styleUrls: ['./action-plan.component.scss'] }) export class ActionPlanComponent { @Input() control: BehaviorSubject = new BehaviorSubject([]); + @Input() keyResultId!: number | null; - activeItem: number = 0; + + activeItem = 0; @ViewChildren('listItem') listItems!: QueryList; - constructor( - private actionService: ActionService, - public dialogService: DialogService, - ) {} + constructor(private actionService: ActionService, + public dialogService: DialogService) {} handleKeyDown(event: Event, currentIndex: number) { let newIndex = currentIndex; @@ -41,7 +41,7 @@ export class ActionPlanComponent { changeItemPosition(newIndex: number, currentIndex: number) { this.activeItem = newIndex; - let currentActionPlan: Action[] = this.control.getValue()!; + const currentActionPlan: Action[] = this.control.getValue()!; this.updateActionTexts(currentActionPlan); moveItemInArray(currentActionPlan, currentIndex, newIndex); currentActionPlan.forEach((action: Action, index: number) => (action.priority = index)); @@ -49,7 +49,8 @@ export class ActionPlanComponent { } updateActionTexts(currentActionPlan: Action[]) { - let texts = Array.from(this.listItems).map((input: any) => input.nativeElement.value); + const texts = Array.from(this.listItems) + .map((input: any) => input.nativeElement.value); currentActionPlan.forEach((action: Action, index: number) => (action.action = texts[index])); } @@ -66,18 +67,19 @@ export class ActionPlanComponent { } drop(event: CdkDragDrop) { - let value: string = (( - event.container.element.nativeElement.children[event.previousIndex].children[1] - )).value; + const value: string = (event.container.element.nativeElement.children[event.previousIndex].children[1] as HTMLInputElement).value; const actions: Action[] = this.control.getValue()!; if (actions[event.previousIndex].action == '' && value != '') { - actions[event.previousIndex] = { ...actions[event.previousIndex], action: value }; + actions[event.previousIndex] = { ...actions[event.previousIndex], + action: value }; this.control.next(actions); } if (event.previousContainer === event.container) { moveItemInArray(event.container.data!, event.previousIndex, event.currentIndex); } else { - transferArrayItem(event.previousContainer.data!, event.container.data!, event.previousIndex, event.currentIndex); + transferArrayItem( + event.previousContainer.data!, event.container.data!, event.previousIndex, event.currentIndex + ); } this.adjustPriorities(); this.activeItem = event.currentIndex; @@ -85,14 +87,14 @@ export class ActionPlanComponent { adjustPriorities() { const actions: Action[] = this.control.getValue()!; - actions.forEach(function (action: Action, index: number) { + actions.forEach(function(action: Action, index: number) { action.priority = index; }); this.control.next(actions); } removeAction(index: number) { - let actions: Action[] = this.control.getValue()!; + const actions: Action[] = this.control.getValue()!; if (this.activeItem == index && this.activeItem > 0) { this.activeItem--; } @@ -103,7 +105,8 @@ export class ActionPlanComponent { .subscribe((result) => { if (result) { if (actions[index].id) { - this.actionService.deleteAction(actions[index].id!).subscribe(); + this.actionService.deleteAction(actions[index].id!) + .subscribe(); } actions.splice(index, 1); this.control.next(actions); @@ -119,13 +122,17 @@ export class ActionPlanComponent { addNewAction() { const actions: Action[] = this.control.getValue()!; - actions.push({ action: '', priority: actions.length, keyResultId: this.keyResultId } as Action); + actions.push({ action: '', + priority: actions.length, + keyResultId: this.keyResultId } as Action); this.control.next(actions); this.activeItem = actions.length - 1; } - /* By default angular material adds a new entry inside the actionplan when the user presses enter - * to disable this behaviour we need this method which prevents the event from firing */ + /* + * By default angular material adds a new entry inside the actionplan when the user presses enter + * to disable this behaviour we need this method which prevents the event from firing + */ preventAddingNewItems(event: Event) { event.preventDefault(); } diff --git a/frontend/src/app/components/application-banner/application-banner.component.html b/frontend/src/app/components/application-banner/application-banner.component.html index db7340e387..62f600d334 100644 --- a/frontend/src/app/components/application-banner/application-banner.component.html +++ b/frontend/src/app/components/application-banner/application-banner.component.html @@ -22,15 +22,12 @@ id="header-accordion" class="content-center" > - +
{{ (quarterLabel$ | async) || quarterLabel$.getValue() - }} + }} Filter
diff --git a/frontend/src/app/components/application-banner/application-banner.component.scss b/frontend/src/app/components/application-banner/application-banner.component.scss index 9efe9b265f..6de85a2771 100644 --- a/frontend/src/app/components/application-banner/application-banner.component.scss +++ b/frontend/src/app/components/application-banner/application-banner.component.scss @@ -1,4 +1,4 @@ -@import "../style/variables"; +@import '../style/variables'; .header-content { padding-left: 1.5rem; diff --git a/frontend/src/app/components/application-banner/application-banner.component.spec.ts b/frontend/src/app/components/application-banner/application-banner.component.spec.ts index 86e542750c..339dbded88 100644 --- a/frontend/src/app/components/application-banner/application-banner.component.spec.ts +++ b/frontend/src/app/components/application-banner/application-banner.component.spec.ts @@ -22,23 +22,25 @@ import { MatInputModule } from '@angular/material/input'; class ResizeObserverMock { observe() {} + unobserve() {} + disconnect() {} } const refreshDataServiceMock = { okrBannerHeightSubject: { - next: jest.fn(), + next: jest.fn() }, - reloadOverviewSubject: of(null), + reloadOverviewSubject: of(null) }; const routeMock = { - queryParams: of(null), + queryParams: of(null) }; describe('ApplicationBannerComponent', () => { - //@ts-ignore + // @ts-ignore global.ResizeObserver = ResizeObserverMock; let component: ApplicationBannerComponent; let fixture: ComponentFixture; @@ -55,19 +57,19 @@ describe('ApplicationBannerComponent', () => { NoopAnimationsModule, FormsModule, ReactiveFormsModule, - MatInputModule, + MatInputModule ], declarations: [ ApplicationBannerComponent, TeamFilterComponent, QuarterFilterComponent, ObjectiveFilterComponent, - OkrTangramComponent, - ], - providers: [ - { provide: RefreshDataService, useValue: refreshDataServiceMock }, - { provide: ActivatedRoute, useValue: routeMock }, + OkrTangramComponent ], + providers: [{ provide: RefreshDataService, + useValue: refreshDataServiceMock }, + { provide: ActivatedRoute, + useValue: routeMock }] }); fixture = TestBed.createComponent(ApplicationBannerComponent); @@ -76,56 +78,57 @@ describe('ApplicationBannerComponent', () => { }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); it('should should hide banner if scrolled down', fakeAsync(() => { - //Set bannerHeight to default - let bannerHeight: number = 160; - //Scroll more than the height of the banner - let scrollTop: number = 180; - //Set lastScrollPosition to smaller than scrollTop => user scrolls down + // Set bannerHeight to default + const bannerHeight = 160; + // Scroll more than the height of the banner + const scrollTop = 180; + // Set lastScrollPosition to smaller than scrollTop => user scrolls down component.lastScrollPosition = 160; component.bannerHeight = bannerHeight; - //Set banner style + // Set banner style component.refreshBanner(scrollTop); tick(600); - //Assert that banner is hidden was changed + // Assert that banner is hidden was changed fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('#okrBanner')).attributes['style']).toContain( - 'top: -' + (PUZZLE_TOP_BAR_HEIGHT + bannerHeight), - ); + expect(fixture.debugElement.query(By.css('#okrBanner')).attributes['style']) + .toContain('top: -' + (PUZZLE_TOP_BAR_HEIGHT + bannerHeight)); })); it('should show banner if scrolled up', fakeAsync(() => { - //Scroll more than the height of the banner - let scrollTop: number = 180; - //Set lastScrollPosition to bigger than scrollTop => user scrolls up + // Scroll more than the height of the banner + const scrollTop = 180; + // Set lastScrollPosition to bigger than scrollTop => user scrolls up component.lastScrollPosition = 200; - //Set banner style + // Set banner style component.refreshBanner(scrollTop); tick(600); - //Assert that banner is visible + // Assert that banner is visible fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('#okrBanner')).attributes['style']).toContain( - 'top: ' + PUZZLE_TOP_BAR_HEIGHT, - ); + expect(fixture.debugElement.query(By.css('#okrBanner')).attributes['style']) + .toContain('top: ' + PUZZLE_TOP_BAR_HEIGHT); })); it('should call setOKRBannerStyle() when changing header appearance', () => { - jest.spyOn(component, 'refreshBanner').mockReturnValue(); + jest.spyOn(component, 'refreshBanner') + .mockReturnValue(); - //Set bannerHeight to default and execute header appearance change + // Set bannerHeight to default and execute header appearance change component.bannerHeight = 160; component.changeHeaderAppearance(); - //Assert that banner is visible + // Assert that banner is visible fixture.detectChanges(); - expect(component.refreshBanner).toHaveBeenCalled(); + expect(component.refreshBanner) + .toHaveBeenCalled(); }); it('should call correct method after call scroll()', () => { @@ -133,6 +136,7 @@ describe('ApplicationBannerComponent', () => { component.scroll(); - expect(component.changeHeaderAppearance).toHaveBeenCalled(); + expect(component.changeHeaderAppearance) + .toHaveBeenCalled(); }); }); diff --git a/frontend/src/app/components/application-banner/application-banner.component.ts b/frontend/src/app/components/application-banner/application-banner.component.ts index d9a064f348..2e0ef4c781 100644 --- a/frontend/src/app/components/application-banner/application-banner.component.ts +++ b/frontend/src/app/components/application-banner/application-banner.component.ts @@ -5,7 +5,7 @@ import { ElementRef, HostListener, OnDestroy, - ViewChild, + ViewChild } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { RefreshDataService } from '../../services/refresh-data.service'; @@ -15,15 +15,20 @@ import { DEFAULT_HEADER_HEIGHT_PX, PUZZLE_TOP_BAR_HEIGHT } from '../../shared/co selector: 'app-application-banner', templateUrl: './application-banner.component.html', styleUrls: ['./application-banner.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, + changeDetection: ChangeDetectionStrategy.OnPush }) export class ApplicationBannerComponent implements AfterViewInit, OnDestroy { @ViewChild('okrBanner') okrBanner!: ElementRef; + quarterLabel$: BehaviorSubject = new BehaviorSubject(''); + panelOpenState = false; + resizeObserver: ResizeObserver; + bannerHeight: number = DEFAULT_HEADER_HEIGHT_PX; - lastScrollPosition: number = 0; + + lastScrollPosition = 0; constructor(private refreshDataService: RefreshDataService) { this.resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => { @@ -41,7 +46,7 @@ export class ApplicationBannerComponent implements AfterViewInit, OnDestroy { } changeHeaderAppearance() { - let scrollTop: number = window.scrollY || document.documentElement.scrollTop; + const scrollTop: number = window.scrollY || document.documentElement.scrollTop; this.refreshBanner(scrollTop); this.lastScrollPosition = scrollTop; } diff --git a/frontend/src/app/components/application-top-bar/application-top-bar.component.html b/frontend/src/app/components/application-top-bar/application-top-bar.component.html index 549b425893..432fecbb55 100644 --- a/frontend/src/app/components/application-top-bar/application-top-bar.component.html +++ b/frontend/src/app/components/application-top-bar/application-top-bar.component.html @@ -1,7 +1,17 @@
- - okr-logo + + okr-logo
@@ -21,7 +35,11 @@ [attr.data-testId]="'help-button'" (click)="window.open(helpSiteUrl, '_blank')" > - + Hilfe @@ -32,15 +50,29 @@ [matMenuTriggerFor]="menu" class="topBarEntry flex-nowrap btn" > - + {{ userFullName }} expand_more expand_less
- - diff --git a/frontend/src/app/components/application-top-bar/application-top-bar.component.scss b/frontend/src/app/components/application-top-bar/application-top-bar.component.scss index b1f8aa6596..30b03d13db 100644 --- a/frontend/src/app/components/application-top-bar/application-top-bar.component.scss +++ b/frontend/src/app/components/application-top-bar/application-top-bar.component.scss @@ -1,4 +1,4 @@ -@import "../style/variables"; +@import '../style/variables'; #topBarHeight { height: $top-bar-height; diff --git a/frontend/src/app/components/application-top-bar/application-top-bar.component.spec.ts b/frontend/src/app/components/application-top-bar/application-top-bar.component.spec.ts index 66fa554e88..f1cf1d3568 100644 --- a/frontend/src/app/components/application-top-bar/application-top-bar.component.spec.ts +++ b/frontend/src/app/components/application-top-bar/application-top-bar.component.spec.ts @@ -20,24 +20,24 @@ import { DialogService } from '../../services/dialog.service'; const oAuthMock = { getIdentityClaims: jest.fn(), logOut: jest.fn(), - hasValidIdToken: jest.fn(), + hasValidIdToken: jest.fn() }; const dialogServiceMock = { - open: jest.fn(), + open: jest.fn() }; const routerMock = { events: of(new NavigationEnd(1, '', '')), - navigateByUrl: jest.fn(), + navigateByUrl: jest.fn() }; const userServiceMock = { - getCurrentUser: () => testUser, + getCurrentUser: () => testUser }; const configServiceMock = { - config$: of({}), + config$: of({}) }; describe('ApplicationTopBarComponent', () => { @@ -47,10 +47,13 @@ describe('ApplicationTopBarComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [MatMenuModule, NoopAnimationsModule, MatDialogModule], + imports: [MatMenuModule, + NoopAnimationsModule, + MatDialogModule], declarations: [ApplicationTopBarComponent], providers: [ - { provide: OAuthService, useValue: oAuthMock }, + { provide: OAuthService, + useValue: oAuthMock }, { provide: HttpClient }, { provide: HttpHandler }, { provide: UrlHelperService }, @@ -58,23 +61,24 @@ describe('ApplicationTopBarComponent', () => { { provide: DateTimeProvider }, { provide: DialogService, - useValue: dialogServiceMock, + useValue: dialogServiceMock }, { provide: Router, - useValue: routerMock, + useValue: routerMock }, { provide: UserService, - useValue: userServiceMock, + useValue: userServiceMock }, { provide: ConfigService, - useValue: configServiceMock, - }, + useValue: configServiceMock + } ], - schemas: [CUSTOM_ELEMENTS_SCHEMA], - }).compileComponents(); + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }) + .compileComponents(); fixture = TestBed.createComponent(ApplicationTopBarComponent); component = fixture.componentInstance; @@ -83,21 +87,26 @@ describe('ApplicationTopBarComponent', () => { }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); it('should set full name from user service', () => { - expect(component.userFullName).toBe('Bob Baumeister'); + expect(component.userFullName) + .toBe('Bob Baumeister'); }); - it('logout function should get called on button click', async () => { - routerMock.navigateByUrl.mockReturnValue(of().toPromise()); + it('logout function should get called on button click', async() => { + routerMock.navigateByUrl.mockReturnValue(of() + .toPromise()); const harness = await loader.getHarness(MatMenuHarness); await harness.open(); fixture.detectChanges(); - harness.getItems().then((items) => { - items[0].click(); - expect(oAuthMock.logOut).toBeCalledTimes(1); - }); + harness.getItems() + .then((items) => { + items[0].click(); + expect(oAuthMock.logOut) + .toBeCalledTimes(1); + }); }); }); diff --git a/frontend/src/app/components/application-top-bar/application-top-bar.component.ts b/frontend/src/app/components/application-top-bar/application-top-bar.component.ts index c5e7640771..dca10dac5a 100644 --- a/frontend/src/app/components/application-top-bar/application-top-bar.component.ts +++ b/frontend/src/app/components/application-top-bar/application-top-bar.component.ts @@ -10,13 +10,17 @@ import { getFullNameFromUser } from '../../shared/types/model/User'; selector: 'app-application-top-bar', templateUrl: './application-top-bar.component.html', styleUrls: ['./application-top-bar.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, + changeDetection: ChangeDetectionStrategy.OnPush }) export class ApplicationTopBarComponent implements OnInit, OnDestroy { - userFullName: string = ''; + userFullName = ''; + menuIsOpen = false; - logoSrc$ = new BehaviorSubject('assets/images/empty.svg'); + + logoSrc$ = new BehaviorSubject('assets/images/empty.svg'); + helpSiteUrl = new BehaviorSubject('https://en.wikipedia.org/wiki/Objectives_and_key_results'); + private subscription?: Subscription; constructor( @@ -24,7 +28,7 @@ export class ApplicationTopBarComponent implements OnInit, OnDestroy { private userService: UserService, private configService: ConfigService, private router: Router, - private readonly cd: ChangeDetectorRef, + private readonly cd: ChangeDetectorRef ) {} ngOnInit(): void { @@ -36,7 +40,7 @@ export class ApplicationTopBarComponent implements OnInit, OnDestroy { if (config.helpSiteUrl) { this.helpSiteUrl.next(config.helpSiteUrl); } - }, + } }); this.initUserFullName(); } @@ -47,9 +51,10 @@ export class ApplicationTopBarComponent implements OnInit, OnDestroy { logOut() { const currentUrlTree = this.router.createUrlTree([], { queryParams: {} }); - this.router.navigateByUrl(currentUrlTree).then(() => { - this.oauthService.logOut(); - }); + this.router.navigateByUrl(currentUrlTree) + .then(() => { + this.oauthService.logOut(); + }); } private initUserFullName() { diff --git a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.html b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.html index f7cc096fe7..28afdb4aae 100644 --- a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.html +++ b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.html @@ -15,7 +15,12 @@ *ngIf="!isComplete && checkIn.writeable" [attr.data-testId]="'edit-check-in'" > - edit check-in + edit check-in
@@ -24,9 +29,7 @@

Wert:

{{ metricCheckIn.value! | unitTransformation: getMetricKeyResult().unit }} - + {{ ordinalCheckIn.zone! }} @@ -50,7 +53,12 @@

Massnahmen:

- +
diff --git a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts index ee75865c64..1f01408053 100644 --- a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts +++ b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.spec.ts @@ -16,7 +16,7 @@ import { DialogTemplateCoreComponent } from '../../shared/custom/dialog-template import { MatDividerModule } from '@angular/material/divider'; const checkInService = { - getAllCheckInOfKeyResult: jest.fn(), + getAllCheckInOfKeyResult: jest.fn() }; describe('CheckInHistoryDialogComponent', () => { @@ -25,33 +25,46 @@ describe('CheckInHistoryDialogComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [CheckInHistoryDialogComponent, DialogTemplateCoreComponent, SpinnerComponent], + declarations: [CheckInHistoryDialogComponent, + DialogTemplateCoreComponent, + SpinnerComponent], - imports: [TranslateModule.forRoot(), MatIconModule, MatProgressSpinner, MatDividerModule, MatDialogModule], + imports: [ + TranslateModule.forRoot(), + MatIconModule, + MatProgressSpinner, + MatDividerModule, + MatDialogModule + ], providers: [ provideRouter([]), provideHttpClient(), provideHttpClientTesting(), TranslateService, DialogService, - { provide: MAT_DIALOG_DATA, useValue: { keyResult: keyResult } }, - { provide: MatDialogRef, useValue: {} }, - ], + { provide: MAT_DIALOG_DATA, + useValue: { keyResult: keyResult } }, + { provide: MatDialogRef, + useValue: {} } + ] }); jest .spyOn(checkInService, 'getAllCheckInOfKeyResult') - .mockReturnValue([checkInMetric, checkInMetricWriteableFalse]); + .mockReturnValue([checkInMetric, + checkInMetricWriteableFalse]); fixture = TestBed.createComponent(CheckInHistoryDialogComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); - it.skip('should not display edit check-in button if writeable is false', async () => { + it.skip('should not display edit check-in button if writeable is false', async() => { const buttons = fixture.debugElement.queryAll(By.css('button')); - expect(buttons.length).toBe(1); + expect(buttons.length) + .toBe(1); }); }); diff --git a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.ts b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.ts index 8c2d5a709c..e562dba5b4 100644 --- a/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.ts +++ b/frontend/src/app/components/check-in-history-dialog/check-in-history-dialog.component.ts @@ -15,12 +15,15 @@ import { CheckInOrdinalMin } from '../../shared/types/model/CheckInOrdinalMin'; @Component({ selector: 'app-check-in-history-dialog', templateUrl: './check-in-history-dialog.component.html', - styleUrls: ['./check-in-history-dialog.component.scss'], + styleUrls: ['./check-in-history-dialog.component.scss'] }) export class CheckInHistoryDialogComponent implements OnInit { keyResult!: KeyResult; + isComplete!: boolean; + checkInHistory$: Observable = of([]); + protected readonly DATE_FORMAT = DATE_FORMAT; constructor( @@ -28,7 +31,7 @@ export class CheckInHistoryDialogComponent implements OnInit { private checkInService: CheckInService, private dialogService: DialogService, public dialogRef: MatDialogRef, - private refreshDataService: RefreshDataService, + private refreshDataService: RefreshDataService ) {} ngOnInit(): void { @@ -41,14 +44,15 @@ export class CheckInHistoryDialogComponent implements OnInit { const dialogRef = this.dialogService.open(CheckInFormComponent, { data: { keyResult: this.keyResult, - checkIn: checkIn, - }, - }); - dialogRef.afterClosed().subscribe(() => { - this.loadCheckInHistory(); - this.refreshDataService.reloadKeyResultSubject.next(); - this.refreshDataService.markDataRefresh(); + checkIn: checkIn + } }); + dialogRef.afterClosed() + .subscribe(() => { + this.loadCheckInHistory(); + this.refreshDataService.reloadKeyResultSubject.next(); + this.refreshDataService.markDataRefresh(); + }); } loadCheckInHistory() { diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts index 6287808fcb..808addfb4f 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts +++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts @@ -26,10 +26,10 @@ describe('CheckInFormComponent', () => { MatRadioModule, ReactiveFormsModule, TranslateTestingModule.withTranslations({ - de: de, - }), + de: de + }) ], - declarations: [CheckInFormMetricComponent], + declarations: [CheckInFormMetricComponent] }); fixture = TestBed.createComponent(CheckInFormMetricComponent); component = fixture.componentInstance; @@ -37,37 +37,50 @@ describe('CheckInFormComponent', () => { component.checkIn = checkInMetric; component.dialogForm = new FormGroup({ value: new FormControl('', [Validators.required]), - confidence: new FormControl(5, [Validators.required, Validators.min(1), Validators.max(10)]), + confidence: new FormControl(5, [Validators.required, + Validators.min(1), + Validators.max(10)]) }); fixture.detectChanges(); }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); - it('should format percent correctly', waitForAsync(async () => { - component.keyResult = { ...keyResultMetric, unit: Unit.PERCENT }; - expect(component.generateUnitLabel()).toEqual('%'); + it('should format percent correctly', waitForAsync(async() => { + component.keyResult = { ...keyResultMetric, + unit: Unit.PERCENT }; + expect(component.generateUnitLabel()) + .toEqual('%'); })); - it('should format chf correctly', waitForAsync(async () => { - component.keyResult = { ...keyResultMetric, unit: Unit.CHF }; - expect(component.generateUnitLabel()).toEqual('CHF'); + it('should format chf correctly', waitForAsync(async() => { + component.keyResult = { ...keyResultMetric, + unit: Unit.CHF }; + expect(component.generateUnitLabel()) + .toEqual('CHF'); })); - it('should format eur correctly', waitForAsync(async () => { - component.keyResult = { ...keyResultMetric, unit: Unit.EUR }; - expect(component.generateUnitLabel()).toEqual('EUR'); + it('should format eur correctly', waitForAsync(async() => { + component.keyResult = { ...keyResultMetric, + unit: Unit.EUR }; + expect(component.generateUnitLabel()) + .toEqual('EUR'); })); - it('should format fte correctly', waitForAsync(async () => { - component.keyResult = { ...keyResultMetric, unit: Unit.FTE }; - expect(component.generateUnitLabel()).toEqual('FTE'); + it('should format fte correctly', waitForAsync(async() => { + component.keyResult = { ...keyResultMetric, + unit: Unit.FTE }; + expect(component.generateUnitLabel()) + .toEqual('FTE'); })); - it('should format number correctly', waitForAsync(async () => { - component.keyResult = { ...keyResultMetric, unit: Unit.NUMBER }; - expect(component.generateUnitLabel()).toEqual(''); + it('should format number correctly', waitForAsync(async() => { + component.keyResult = { ...keyResultMetric, + unit: Unit.NUMBER }; + expect(component.generateUnitLabel()) + .toEqual(''); })); }); diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts index 0b77bd593a..ca77d2ef0b 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts +++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts @@ -10,22 +10,27 @@ import { CheckInMetricMin } from '../../../shared/types/model/CheckInMetricMin'; selector: 'app-check-in-form-metric', templateUrl: './check-in-form-metric.component.html', styleUrls: ['./check-in-form-metric.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, + changeDetection: ChangeDetectionStrategy.OnPush }) export class CheckInFormMetricComponent implements OnInit { @Input() keyResult!: KeyResultMetric; + @Input() checkIn!: CheckInMin; + @Input() dialogForm!: FormGroup; + protected readonly formInputCheck = formInputCheck; + protected readonly hasFormFieldErrors = hasFormFieldErrors; constructor(private translate: TranslateService) {} ngOnInit() { - this.dialogForm.controls['value'].setValidators([Validators.required, Validators.pattern('^-?\\d+\\.?\\d*$')]); + this.dialogForm.controls['value'].setValidators([Validators.required, + Validators.pattern('^-?\\d+\\.?\\d*$')]); } generateUnitLabel(): string { diff --git a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts index acd3577f2e..8498b4133d 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts +++ b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts @@ -3,16 +3,23 @@ import { MetricCheckInDirective } from './metric-check-in-directive'; describe('MetricCheckInDirective', () => { it('create an instance', () => { const directive = new MetricCheckInDirective(); - expect(directive).toBeTruthy(); + expect(directive) + .toBeTruthy(); }); it.each([ - ['HelloWorld200', 200], - ['200HelloWorld', 200], - ["200'000", 200000], - ['1050&%ç*', 1050], - ['-1', -1], - ['-ç13&%', -13], + ['HelloWorld200', + 200], + ['200HelloWorld', + 200], + ["200'000", + 200000], + ['1050&%ç*', + 1050], + ['-1', + -1], + ['-ç13&%', + -13] ])('should parse value %s correctly to %s', (value: string, expected: number) => { const mockOnChange = jest.fn(); const directive = new MetricCheckInDirective(); @@ -20,6 +27,7 @@ describe('MetricCheckInDirective', () => { directive.handleInput(value); - expect(mockOnChange).toHaveBeenCalledWith(expected); + expect(mockOnChange) + .toHaveBeenCalledWith(expected); }); }); diff --git a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts index d7fa625061..98f4638545 100644 --- a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts +++ b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts @@ -3,16 +3,15 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Directive({ selector: '[metricCheckIn]', - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MetricCheckInDirective), - multi: true, - }, - ], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MetricCheckInDirective), + multi: true + }] }) export class MetricCheckInDirective implements ControlValueAccessor { private onChange: (value: number | null) => void = () => {}; + protected readonly CHAR_REGEX = /[^0-9.]/g; writeValue(value: any): void { @@ -30,10 +29,13 @@ export class MetricCheckInDirective implements ControlValueAccessor { @HostListener('input', ['$event.target.value']) handleInput(param: string): void { const value: string = param || '0'; - if (value.toString().at(0) == '-') { - this.onChange(+('-' + value.toString().replace(this.CHAR_REGEX, ''))); + if (value.toString() + .at(0) == '-') { + this.onChange(+('-' + value.toString() + .replace(this.CHAR_REGEX, ''))); return; } - this.onChange(Number(value.toString().replace(this.CHAR_REGEX, ''))); + this.onChange(Number(value.toString() + .replace(this.CHAR_REGEX, ''))); } } diff --git a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html index 1477819976..a15793ca9b 100644 --- a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html +++ b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html @@ -1,26 +1,46 @@
- - + +
Fail:  Commit / Target / Stretch noch nicht erreicht
- +
Commit: {{ keyResult.commitZone }}
- +
Target: {{ keyResult.targetZone }}
- +
Stretch: {{ keyResult.stretchZone }}
diff --git a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.scss b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.scss index 62b280fbef..b7febe31a8 100644 --- a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.scss +++ b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.scss @@ -1,4 +1,4 @@ -@import "../style/variables"; +@import '../style/variables'; .submit { background-color: $pz-dark-blue; diff --git a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.spec.ts b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.spec.ts index f1b32bf4c0..62dd6f82e8 100644 --- a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.spec.ts +++ b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.spec.ts @@ -27,57 +27,66 @@ describe('CheckInFormOrdinalComponent', () => { MatSelectModule, MatInputModule, MatRadioModule, - ReactiveFormsModule, + ReactiveFormsModule ], - declarations: [CheckInFormOrdinalComponent], + declarations: [CheckInFormOrdinalComponent] }); fixture = TestBed.createComponent(CheckInFormOrdinalComponent); component = fixture.componentInstance; component.keyResult = keyResultOrdinalMin as unknown as KeyResultOrdinal; component.dialogForm = new FormGroup({ value: new FormControl('', [Validators.required]), - confidence: new FormControl(5, [Validators.required, Validators.min(1), Validators.max(10)]), + confidence: new FormControl(5, [Validators.required, + Validators.min(1), + Validators.max(10)]) }); fixture.detectChanges(); loader = TestbedHarnessEnvironment.loader(fixture); }); it('should create', () => { - expect(component).toBeTruthy(); + expect(component) + .toBeTruthy(); }); - it('should set zone of check-in to fail if value is empty', waitForAsync(async () => { - expect(component.dialogForm.controls['value'].value).toBe(''); + it('should set zone of check-in to fail if value is empty', waitForAsync(async() => { + expect(component.dialogForm.controls['value'].value) + .toBe(''); })); - it('should set zone to Fail', waitForAsync(async () => { + it('should set zone to Fail', waitForAsync(async() => { const radioButtons = await loader.getAllHarnesses(MatRadioButtonHarness); await radioButtons[0].check(); - expect(component.dialogForm.controls['value'].value).toBe(Zone.FAIL); + expect(component.dialogForm.controls['value'].value) + .toBe(Zone.FAIL); })); - it('should set zone to Commit', waitForAsync(async () => { + it('should set zone to Commit', waitForAsync(async() => { const radioButtons = await loader.getAllHarnesses(MatRadioButtonHarness); await radioButtons[1].check(); - expect(component.dialogForm.controls['value'].value).toBe(Zone.COMMIT); + expect(component.dialogForm.controls['value'].value) + .toBe(Zone.COMMIT); })); - it('should set zone to Target', waitForAsync(async () => { + it('should set zone to Target', waitForAsync(async() => { const radioButtons = await loader.getAllHarnesses(MatRadioButtonHarness); await radioButtons[2].check(); - expect(component.dialogForm.controls['value'].value).toBe(Zone.TARGET); + expect(component.dialogForm.controls['value'].value) + .toBe(Zone.TARGET); })); - it('should set zone to Stretch', waitForAsync(async () => { + it('should set zone to Stretch', waitForAsync(async() => { const radioButtons = await loader.getAllHarnesses(MatRadioButtonHarness); await radioButtons[3].check(); - expect(component.dialogForm.controls['value'].value).toBe(Zone.STRETCH); + expect(component.dialogForm.controls['value'].value) + .toBe(Zone.STRETCH); })); - it('should be able to switch options ', waitForAsync(async () => { + it('should be able to switch options ', waitForAsync(async() => { const radioButtons = await loader.getAllHarnesses(MatRadioButtonHarness); await radioButtons[3].check(); await radioButtons[1].check(); - expect(component.dialogForm.controls['value'].value).toBe(Zone.COMMIT); + expect(component.dialogForm.controls['value'].value) + .toBe(Zone.COMMIT); })); }); diff --git a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.ts b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.ts index 192c5156fb..ed8354c380 100644 --- a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.ts +++ b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.ts @@ -7,14 +7,17 @@ import { CheckInMin } from '../../../shared/types/model/CheckInMin'; @Component({ selector: 'app-check-in-form-ordinal', templateUrl: './check-in-form-ordinal.component.html', - styleUrls: ['./check-in-form-ordinal.component.scss'], + styleUrls: ['./check-in-form-ordinal.component.scss'] }) export class CheckInFormOrdinalComponent { @Input() keyResult!: KeyResultOrdinal; + @Input() checkIn!: CheckInMin; + @Input() dialogForm!: FormGroup; + protected readonly Zone = Zone; } diff --git a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html index 4c0fbdbb69..e979005f62 100644 --- a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html +++ b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.html @@ -12,12 +12,14 @@
- - -
+ +
{{ action.action }}
@@ -25,8 +27,7 @@
- Kommentar/ Veränderung seit letztem Check-in (optional):